mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 13:55:38 +00:00
Common: Drop String, add SmallString
This commit is contained in:
parent
3c68543491
commit
ac0601f408
|
@ -46,8 +46,8 @@ add_library(common
|
||||||
settings_interface.h
|
settings_interface.h
|
||||||
sha1_digest.cpp
|
sha1_digest.cpp
|
||||||
sha1_digest.h
|
sha1_digest.h
|
||||||
string.cpp
|
small_string.cpp
|
||||||
string.h
|
small_string.h
|
||||||
string_util.cpp
|
string_util.cpp
|
||||||
string_util.h
|
string_util.h
|
||||||
thirdparty/thread_pool.cpp
|
thirdparty/thread_pool.cpp
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<ClInclude Include="scoped_guard.h" />
|
<ClInclude Include="scoped_guard.h" />
|
||||||
<ClInclude Include="settings_interface.h" />
|
<ClInclude Include="settings_interface.h" />
|
||||||
<ClInclude Include="sha1_digest.h" />
|
<ClInclude Include="sha1_digest.h" />
|
||||||
<ClInclude Include="string.h" />
|
<ClInclude Include="small_string.h" />
|
||||||
<ClInclude Include="heterogeneous_containers.h" />
|
<ClInclude Include="heterogeneous_containers.h" />
|
||||||
<ClInclude Include="string_util.h" />
|
<ClInclude Include="string_util.h" />
|
||||||
<ClInclude Include="thirdparty\StackWalker.h" />
|
<ClInclude Include="thirdparty\StackWalker.h" />
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
<ClCompile Include="minizip_helpers.cpp" />
|
<ClCompile Include="minizip_helpers.cpp" />
|
||||||
<ClCompile Include="progress_callback.cpp" />
|
<ClCompile Include="progress_callback.cpp" />
|
||||||
<ClCompile Include="sha1_digest.cpp" />
|
<ClCompile Include="sha1_digest.cpp" />
|
||||||
<ClCompile Include="string.cpp" />
|
<ClCompile Include="small_string.cpp" />
|
||||||
<ClCompile Include="string_util.cpp" />
|
<ClCompile Include="string_util.cpp" />
|
||||||
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
<ClCompile Include="thirdparty\StackWalker.cpp" />
|
||||||
<ClCompile Include="threading.cpp" />
|
<ClCompile Include="threading.cpp" />
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<ClInclude Include="heap_array.h" />
|
<ClInclude Include="heap_array.h" />
|
||||||
<ClInclude Include="rectangle.h" />
|
<ClInclude Include="rectangle.h" />
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
<ClInclude Include="string.h" />
|
<ClInclude Include="small_string.h" />
|
||||||
<ClInclude Include="byte_stream.h" />
|
<ClInclude Include="byte_stream.h" />
|
||||||
<ClInclude Include="timer.h" />
|
<ClInclude Include="timer.h" />
|
||||||
<ClInclude Include="assert.h" />
|
<ClInclude Include="assert.h" />
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
<ClInclude Include="memmap.h" />
|
<ClInclude Include="memmap.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="string.cpp" />
|
<ClCompile Include="small_string.cpp" />
|
||||||
<ClCompile Include="byte_stream.cpp" />
|
<ClCompile Include="byte_stream.cpp" />
|
||||||
<ClCompile Include="log.cpp" />
|
<ClCompile Include="log.cpp" />
|
||||||
<ClCompile Include="timer.cpp" />
|
<ClCompile Include="timer.cpp" />
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "file_system.h"
|
#include "file_system.h"
|
||||||
#include "string.h"
|
#include "small_string.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
@ -36,7 +36,7 @@ static LOGLEVEL s_filter_level = LOGLEVEL_TRACE;
|
||||||
static Common::Timer::Value s_startTimeStamp = Common::Timer::GetCurrentValue();
|
static Common::Timer::Value s_startTimeStamp = Common::Timer::GetCurrentValue();
|
||||||
|
|
||||||
static bool s_console_output_enabled = false;
|
static bool s_console_output_enabled = false;
|
||||||
static String s_console_output_channel_filter;
|
static std::string s_console_output_channel_filter;
|
||||||
static LOGLEVEL s_console_output_level_filter = LOGLEVEL_TRACE;
|
static LOGLEVEL s_console_output_level_filter = LOGLEVEL_TRACE;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -46,12 +46,12 @@ static HANDLE s_hConsoleStdErr = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool s_debug_output_enabled = false;
|
static bool s_debug_output_enabled = false;
|
||||||
static String s_debug_output_channel_filter;
|
static std::string s_debug_output_channel_filter;
|
||||||
static LOGLEVEL s_debug_output_level_filter = LOGLEVEL_TRACE;
|
static LOGLEVEL s_debug_output_level_filter = LOGLEVEL_TRACE;
|
||||||
|
|
||||||
static bool s_file_output_enabled = false;
|
static bool s_file_output_enabled = false;
|
||||||
static bool s_file_output_timestamp = false;
|
static bool s_file_output_timestamp = false;
|
||||||
static String s_file_output_channel_filter;
|
static std::string s_file_output_channel_filter;
|
||||||
static LOGLEVEL s_file_output_level_filter = LOGLEVEL_TRACE;
|
static LOGLEVEL s_file_output_level_filter = LOGLEVEL_TRACE;
|
||||||
std::unique_ptr<std::FILE, void (*)(std::FILE*)> s_fileOutputHandle(nullptr, [](std::FILE* fp) {
|
std::unique_ptr<std::FILE, void (*)(std::FILE*)> s_fileOutputHandle(nullptr, [](std::FILE* fp) {
|
||||||
if (fp)
|
if (fp)
|
||||||
|
@ -242,7 +242,7 @@ static void ConsoleOutputLogCallback(void* pUserParam, const char* channelName,
|
||||||
LOGLEVEL level, const char* message)
|
LOGLEVEL level, const char* message)
|
||||||
{
|
{
|
||||||
if (!s_console_output_enabled || level > s_console_output_level_filter ||
|
if (!s_console_output_enabled || level > s_console_output_level_filter ||
|
||||||
s_console_output_channel_filter.Find(channelName) >= 0)
|
s_console_output_channel_filter.find(channelName) != std::string::npos)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ static void DebugOutputLogCallback(void* pUserParam, const char* channelName, co
|
||||||
const char* message)
|
const char* message)
|
||||||
{
|
{
|
||||||
if (!s_debug_output_enabled || level > s_debug_output_level_filter ||
|
if (!s_debug_output_enabled || level > s_debug_output_level_filter ||
|
||||||
s_debug_output_channel_filter.Find(functionName) >= 0)
|
s_debug_output_channel_filter.find(functionName) != std::string::npos)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -393,7 +393,7 @@ void SetDebugOutputParams(bool enabled, const char* channelFilter /* = nullptr *
|
||||||
static void FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level,
|
static void FileOutputLogCallback(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level,
|
||||||
const char* message)
|
const char* message)
|
||||||
{
|
{
|
||||||
if (level > s_file_output_level_filter || s_file_output_channel_filter.Find(channelName) >= 0)
|
if (level > s_file_output_level_filter || s_file_output_channel_filter.find(channelName) != std::string::npos)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FormatLogMessageAndPrint(
|
FormatLogMessageAndPrint(
|
||||||
|
|
|
@ -18,7 +18,7 @@ void ProgressCallback::SetFormattedStatusText(const char* Format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, Format);
|
va_start(ap, Format);
|
||||||
str.FormatVA(Format, ap);
|
str.format_va(Format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
SetStatusText(str);
|
SetStatusText(str);
|
||||||
|
@ -30,7 +30,7 @@ void ProgressCallback::DisplayFormattedError(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
DisplayError(str);
|
DisplayError(str);
|
||||||
|
@ -42,7 +42,7 @@ void ProgressCallback::DisplayFormattedWarning(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
DisplayWarning(str);
|
DisplayWarning(str);
|
||||||
|
@ -54,7 +54,7 @@ void ProgressCallback::DisplayFormattedInformation(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
DisplayInformation(str);
|
DisplayInformation(str);
|
||||||
|
@ -66,7 +66,7 @@ void ProgressCallback::DisplayFormattedDebugMessage(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
DisplayDebugMessage(str);
|
DisplayDebugMessage(str);
|
||||||
|
@ -78,7 +78,7 @@ void ProgressCallback::DisplayFormattedModalError(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
ModalError(str);
|
ModalError(str);
|
||||||
|
@ -90,7 +90,7 @@ bool ProgressCallback::DisplayFormattedModalConfirmation(const char* format, ...
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return ModalConfirmation(str);
|
return ModalConfirmation(str);
|
||||||
|
@ -102,7 +102,7 @@ void ProgressCallback::DisplayFormattedModalInformation(const char* format, ...)
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
ModalInformation(str);
|
ModalInformation(str);
|
||||||
|
@ -312,10 +312,10 @@ void ConsoleProgressCallback::Clear()
|
||||||
{
|
{
|
||||||
SmallString message;
|
SmallString message;
|
||||||
for (u32 i = 0; i < COLUMNS; i++)
|
for (u32 i = 0; i < COLUMNS; i++)
|
||||||
message.AppendCharacter(' ');
|
message.append(' ');
|
||||||
message.AppendCharacter('\r');
|
message.append('\r');
|
||||||
|
|
||||||
std::fwrite(message.GetCharArray(), message.GetLength(), 1, stderr);
|
std::fwrite(message.c_str(), message.length(), 1, stderr);
|
||||||
std::fflush(stderr);
|
std::fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ void ConsoleProgressCallback::Redraw(bool update_value_only)
|
||||||
if (percent_complete > 100.0f)
|
if (percent_complete > 100.0f)
|
||||||
percent_complete = 100.0f;
|
percent_complete = 100.0f;
|
||||||
|
|
||||||
const u32 current_length = m_status_text.GetLength() + 14;
|
const u32 current_length = static_cast<u32>(m_status_text.length()) + 14;
|
||||||
const u32 max_bar_length = (current_length < COLUMNS) ? COLUMNS - current_length : 0;
|
const u32 max_bar_length = (current_length < COLUMNS) ? COLUMNS - current_length : 0;
|
||||||
const u32 current_bar_length =
|
const u32 current_bar_length =
|
||||||
(max_bar_length > 0) ? (static_cast<u32>(percent_complete / 100.0f * (float)max_bar_length)) : 0;
|
(max_bar_length > 0) ? (static_cast<u32>(percent_complete / 100.0f * (float)max_bar_length)) : 0;
|
||||||
|
@ -340,25 +340,25 @@ void ConsoleProgressCallback::Redraw(bool update_value_only)
|
||||||
m_last_percent_complete = percent_complete;
|
m_last_percent_complete = percent_complete;
|
||||||
|
|
||||||
SmallString message;
|
SmallString message;
|
||||||
message.AppendString(m_status_text);
|
message.append(m_status_text);
|
||||||
message.AppendFormattedString(" [%.2f%%]", percent_complete);
|
message.append_fmt(" [{:.2f}%]", percent_complete);
|
||||||
|
|
||||||
if (max_bar_length > 0)
|
if (max_bar_length > 0)
|
||||||
{
|
{
|
||||||
message.AppendString(" |");
|
message.append(" |");
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
for (i = 0; i < current_bar_length; i++)
|
for (i = 0; i < current_bar_length; i++)
|
||||||
message.AppendCharacter('=');
|
message.append('=');
|
||||||
for (; i < max_bar_length; i++)
|
for (; i < max_bar_length; i++)
|
||||||
message.AppendCharacter(' ');
|
message.append(' ');
|
||||||
|
|
||||||
message.AppendString("|");
|
message.append('|');
|
||||||
}
|
}
|
||||||
|
|
||||||
message.AppendCharacter('\r');
|
message.append('\r');
|
||||||
|
|
||||||
std::fwrite(message.GetCharArray(), message.GetLength(), 1, stderr);
|
std::fwrite(message.c_str(), message.length(), 1, stderr);
|
||||||
std::fflush(stderr);
|
std::fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "string.h"
|
#include "small_string.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
class ByteStream;
|
class ByteStream;
|
||||||
|
@ -73,7 +73,7 @@ protected:
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
State* next_saved_state;
|
State* next_saved_state;
|
||||||
String status_text;
|
std::string status_text;
|
||||||
u32 progress_range;
|
u32 progress_range;
|
||||||
u32 progress_value;
|
u32 progress_value;
|
||||||
u32 base_progress_value;
|
u32 base_progress_value;
|
||||||
|
@ -82,7 +82,7 @@ protected:
|
||||||
|
|
||||||
bool m_cancellable;
|
bool m_cancellable;
|
||||||
bool m_cancelled;
|
bool m_cancelled;
|
||||||
String m_status_text;
|
std::string m_status_text;
|
||||||
u32 m_progress_range;
|
u32 m_progress_range;
|
||||||
u32 m_progress_value;
|
u32 m_progress_value;
|
||||||
|
|
||||||
|
|
699
src/common/small_string.cpp
Normal file
699
src/common/small_string.cpp
Normal file
|
@ -0,0 +1,699 @@
|
||||||
|
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#include "small_string.h"
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define CASE_COMPARE _stricmp
|
||||||
|
#define CASE_N_COMPARE _strnicmp
|
||||||
|
#else
|
||||||
|
#define CASE_COMPARE strcasecmp
|
||||||
|
#define CASE_N_COMPARE strncasecmp
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase() = default;
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(const SmallStringBase& copy)
|
||||||
|
{
|
||||||
|
assign(copy.m_buffer, copy.m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(const char* str)
|
||||||
|
{
|
||||||
|
assign(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(const char* str, u32 count)
|
||||||
|
{
|
||||||
|
assign(str, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(SmallStringBase&& move)
|
||||||
|
{
|
||||||
|
assign(std::move(move));
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(const std::string_view& sv)
|
||||||
|
{
|
||||||
|
assign(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::SmallStringBase(const std::string& str)
|
||||||
|
{
|
||||||
|
assign(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase::~SmallStringBase()
|
||||||
|
{
|
||||||
|
if (m_on_heap)
|
||||||
|
std::free(m_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::reserve(u32 new_reserve)
|
||||||
|
{
|
||||||
|
if (m_buffer_size >= new_reserve)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_on_heap)
|
||||||
|
{
|
||||||
|
char* new_ptr = static_cast<char*>(std::realloc(m_buffer, new_reserve));
|
||||||
|
if (!new_ptr)
|
||||||
|
Panic("Memory allocation failed.");
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::memset(new_ptr + m_length, 0, new_reserve - m_length);
|
||||||
|
#endif
|
||||||
|
m_buffer = new_ptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char* new_ptr = static_cast<char*>(std::malloc(new_reserve));
|
||||||
|
if (!new_ptr)
|
||||||
|
Panic("Memory allocation failed.");
|
||||||
|
|
||||||
|
if (m_length > 0)
|
||||||
|
std::memcpy(new_ptr, m_buffer, m_length);
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::memset(new_ptr + m_length, 0, new_reserve - m_length);
|
||||||
|
#else
|
||||||
|
new_ptr[m_length] = 0;
|
||||||
|
#endif
|
||||||
|
m_buffer = new_ptr;
|
||||||
|
m_on_heap = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::shrink_to_fit()
|
||||||
|
{
|
||||||
|
if (!m_on_heap || m_length == m_buffer_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_length == 0)
|
||||||
|
{
|
||||||
|
std::free(m_buffer);
|
||||||
|
m_buffer_size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* new_ptr = static_cast<char*>(std::realloc(m_buffer, m_length));
|
||||||
|
if (!new_ptr)
|
||||||
|
Panic("Memory allocation failed.");
|
||||||
|
|
||||||
|
m_buffer = new_ptr;
|
||||||
|
m_buffer_size = m_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view SmallStringBase::view() const
|
||||||
|
{
|
||||||
|
return (m_length == 0) ? std::string_view() : std::string_view(m_buffer, m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase& SmallStringBase::operator=(SmallStringBase&& move)
|
||||||
|
{
|
||||||
|
assign(move);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase& SmallStringBase::operator=(const std::string_view& str)
|
||||||
|
{
|
||||||
|
assign(str);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase& SmallStringBase::operator=(const std::string& str)
|
||||||
|
{
|
||||||
|
assign(str);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase& SmallStringBase::operator=(const char* str)
|
||||||
|
{
|
||||||
|
assign(str);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallStringBase& SmallStringBase::operator=(const SmallStringBase& copy)
|
||||||
|
{
|
||||||
|
assign(copy);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::make_room_for(u32 space)
|
||||||
|
{
|
||||||
|
const u32 required_size = m_length + space + 1;
|
||||||
|
if (m_buffer_size >= required_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
reserve(std::max(required_size, m_buffer_size * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(const char* str, u32 length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
make_room_for(length);
|
||||||
|
|
||||||
|
DebugAssert((length + m_length) < m_buffer_size);
|
||||||
|
|
||||||
|
std::memcpy(m_buffer + m_length, str, length);
|
||||||
|
m_length += length;
|
||||||
|
m_buffer[m_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(const char* str, u32 length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
make_room_for(length);
|
||||||
|
|
||||||
|
DebugAssert((length + m_length) < m_buffer_size);
|
||||||
|
|
||||||
|
std::memmove(m_buffer + length, m_buffer, m_length);
|
||||||
|
std::memcpy(m_buffer, str, length);
|
||||||
|
m_length += length;
|
||||||
|
m_buffer[m_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(char c)
|
||||||
|
{
|
||||||
|
append(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(const SmallStringBase& str)
|
||||||
|
{
|
||||||
|
append(str.m_buffer, str.m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(const char* str)
|
||||||
|
{
|
||||||
|
append(str, static_cast<u32>(std::strlen(str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(const std::string& str)
|
||||||
|
{
|
||||||
|
append(str.c_str(), static_cast<u32>(str.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append(const std::string_view& str)
|
||||||
|
{
|
||||||
|
append(str.data(), static_cast<u32>(str.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append_format(const char* format, ...)
|
||||||
|
{
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
append_format_va(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::append_format_va(const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
// We have a 1KB byte buffer on the stack here. If this is too little, we'll grow it via the heap,
|
||||||
|
// but 1KB should be enough for most strings.
|
||||||
|
char stack_buffer[1024];
|
||||||
|
char* heap_buffer = nullptr;
|
||||||
|
char* buffer = stack_buffer;
|
||||||
|
u32 buffer_size = static_cast<u32>(std::size(stack_buffer));
|
||||||
|
u32 written;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
std::va_list ap_copy;
|
||||||
|
va_copy(ap_copy, ap);
|
||||||
|
const int ret = std::vsnprintf(buffer, buffer_size, format, ap_copy);
|
||||||
|
va_end(ap_copy);
|
||||||
|
if (ret < 0 || ((u32)ret >= (buffer_size - 1)))
|
||||||
|
{
|
||||||
|
buffer_size *= 2;
|
||||||
|
buffer = heap_buffer = reinterpret_cast<char*>(std::realloc(heap_buffer, buffer_size));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = static_cast<u32>(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
append(buffer, written);
|
||||||
|
|
||||||
|
if (heap_buffer)
|
||||||
|
std::free(heap_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(char c)
|
||||||
|
{
|
||||||
|
prepend(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(const SmallStringBase& str)
|
||||||
|
{
|
||||||
|
prepend(str.m_buffer, str.m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(const char* str)
|
||||||
|
{
|
||||||
|
prepend(str, static_cast<u32>(std::strlen(str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(const std::string& str)
|
||||||
|
{
|
||||||
|
prepend(str.c_str(), static_cast<u32>(str.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend(const std::string_view& str)
|
||||||
|
{
|
||||||
|
prepend(str.data(), static_cast<u32>(str.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend_format(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
prepend_format_va(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::prepend_format_va(const char* format, va_list ArgPtr)
|
||||||
|
{
|
||||||
|
// We have a 1KB byte buffer on the stack here. If this is too little, we'll grow it via the heap,
|
||||||
|
// but 1KB should be enough for most strings.
|
||||||
|
char stack_buffer[1024];
|
||||||
|
char* heap_buffer = NULL;
|
||||||
|
char* buffer = stack_buffer;
|
||||||
|
u32 buffer_size = static_cast<u32>(std::size(stack_buffer));
|
||||||
|
u32 written;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int ret = std::vsnprintf(buffer, buffer_size, format, ArgPtr);
|
||||||
|
if (ret < 0 || (static_cast<u32>(ret) >= (buffer_size - 1)))
|
||||||
|
{
|
||||||
|
buffer_size *= 2;
|
||||||
|
buffer = heap_buffer = reinterpret_cast<char*>(std::realloc(heap_buffer, buffer_size));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = static_cast<u32>(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepend(buffer, written);
|
||||||
|
|
||||||
|
if (heap_buffer)
|
||||||
|
std::free(heap_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::insert(s32 offset, const char* str)
|
||||||
|
{
|
||||||
|
insert(offset, str, static_cast<u32>(std::strlen(str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::insert(s32 offset, const SmallStringBase& str)
|
||||||
|
{
|
||||||
|
insert(offset, str, str.m_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::insert(s32 offset, const char* str, u32 length)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
make_room_for(length);
|
||||||
|
|
||||||
|
// calc real offset
|
||||||
|
u32 real_offset;
|
||||||
|
if (offset < 0)
|
||||||
|
real_offset = static_cast<u32>(std::max<s32>(0, static_cast<s32>(m_length) + offset));
|
||||||
|
else
|
||||||
|
real_offset = std::min(static_cast<u32>(offset), m_length);
|
||||||
|
|
||||||
|
// determine number of characters after offset
|
||||||
|
DebugAssert(real_offset <= m_length);
|
||||||
|
const u32 chars_after_offset = m_length - real_offset;
|
||||||
|
if (chars_after_offset > 0)
|
||||||
|
std::memmove(m_buffer + offset + length, m_buffer + offset, chars_after_offset);
|
||||||
|
|
||||||
|
// insert the string
|
||||||
|
std::memcpy(m_buffer + real_offset, str, length);
|
||||||
|
m_length += length;
|
||||||
|
|
||||||
|
// ensure null termination
|
||||||
|
m_buffer[m_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::insert(s32 offset, const std::string& str)
|
||||||
|
{
|
||||||
|
insert(offset, str.c_str(), static_cast<u32>(str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::insert(s32 offset, const std::string_view& str)
|
||||||
|
{
|
||||||
|
insert(offset, str.data(), static_cast<u32>(str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::format(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
format_va(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::format_va(const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
append_format_va(format, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(const SmallStringBase& copy)
|
||||||
|
{
|
||||||
|
assign(copy.c_str(), copy.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(const char* str)
|
||||||
|
{
|
||||||
|
assign(str, static_cast<u32>(std::strlen(str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(const char* str, u32 length)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
if (length > 0)
|
||||||
|
append(str, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(SmallStringBase&& move)
|
||||||
|
{
|
||||||
|
if (move.m_on_heap)
|
||||||
|
{
|
||||||
|
if (m_on_heap)
|
||||||
|
std::free(m_buffer);
|
||||||
|
m_buffer = move.m_buffer;
|
||||||
|
m_buffer_size = move.m_buffer_size;
|
||||||
|
m_length = move.m_length;
|
||||||
|
m_on_heap = true;
|
||||||
|
move.m_buffer = nullptr;
|
||||||
|
move.m_buffer_size = 0;
|
||||||
|
move.m_length = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assign(move.m_buffer, move.m_buffer_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(const std::string& str)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
append(str.data(), static_cast<u32>(str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::assign(const std::string_view& str)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
append(str.data(), static_cast<u32>(str.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::equals(const char* str) const
|
||||||
|
{
|
||||||
|
if (m_length == 0)
|
||||||
|
return (std::strlen(str) == 0);
|
||||||
|
else
|
||||||
|
return (std::strcmp(m_buffer, str) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::equals(const SmallStringBase& str) const
|
||||||
|
{
|
||||||
|
return (m_length == str.m_length && (m_length == 0 || std::strcmp(m_buffer, str.m_buffer) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::equals(const std::string_view& str) const
|
||||||
|
{
|
||||||
|
return (m_length == static_cast<u32>(str.length()) &&
|
||||||
|
(m_length == 0 || CASE_N_COMPARE(m_buffer, str.data(), m_length) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::iequals(const char* otherText) const
|
||||||
|
{
|
||||||
|
if (m_length == 0)
|
||||||
|
return (std::strlen(otherText) == 0);
|
||||||
|
else
|
||||||
|
return (CASE_COMPARE(m_buffer, otherText) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::iequals(const SmallStringBase& str) const
|
||||||
|
{
|
||||||
|
return (m_length == str.m_length && (m_length == 0 || std::strcmp(m_buffer, str.m_buffer) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::iequals(const std::string_view& str) const
|
||||||
|
{
|
||||||
|
return (m_length == static_cast<u32>(str.length()) &&
|
||||||
|
(m_length == 0 || CASE_N_COMPARE(m_buffer, str.data(), m_length) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmallStringBase::compare(const SmallStringBase& str) const
|
||||||
|
{
|
||||||
|
return std::strcmp(m_buffer, str.m_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmallStringBase::compare(const char* otherText) const
|
||||||
|
{
|
||||||
|
return std::strcmp(m_buffer, otherText);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmallStringBase::icompare(const SmallStringBase& otherString) const
|
||||||
|
{
|
||||||
|
return CASE_COMPARE(m_buffer, otherString.m_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmallStringBase::icompare(const char* otherText) const
|
||||||
|
{
|
||||||
|
return CASE_COMPARE(m_buffer, otherText);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::starts_with(const char* str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = static_cast<u32>(std::strlen(str));
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (case_sensitive) ? (std::strncmp(str, m_buffer, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str, m_buffer, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::starts_with(const SmallStringBase& str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = str.m_length;
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (case_sensitive) ? (std::strncmp(str.m_buffer, m_buffer, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str.m_buffer, m_buffer, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::starts_with(const std::string_view& str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = static_cast<u32>(str.length());
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::ends_with(const char* str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = static_cast<u32>(std::strlen(str));
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u32 start_offset = m_length - other_length;
|
||||||
|
return (case_sensitive) ? (std::strncmp(str, m_buffer + start_offset, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str, m_buffer + start_offset, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::ends_with(const SmallStringBase& str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = str.m_length;
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 start_offset = m_length - other_length;
|
||||||
|
return (case_sensitive) ? (std::strncmp(str.m_buffer, m_buffer + start_offset, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str.m_buffer, m_buffer + start_offset, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SmallStringBase::ends_with(const std::string_view& str, bool case_sensitive) const
|
||||||
|
{
|
||||||
|
const u32 other_length = static_cast<u32>(str.length());
|
||||||
|
if (other_length > m_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const u32 start_offset = m_length - other_length;
|
||||||
|
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer + start_offset, other_length) == 0) :
|
||||||
|
(CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::clear()
|
||||||
|
{
|
||||||
|
// in debug, zero whole string, in release, zero only the first character
|
||||||
|
#if _DEBUG
|
||||||
|
std::memset(m_buffer, 0, m_buffer_size);
|
||||||
|
#else
|
||||||
|
m_buffer[0] = '\0';
|
||||||
|
#endif
|
||||||
|
m_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SmallStringBase::find(char c, u32 offset) const
|
||||||
|
{
|
||||||
|
if (m_length == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DebugAssert(offset <= m_length);
|
||||||
|
const char* at = std::strchr(m_buffer + offset, c);
|
||||||
|
return at ? static_cast<s32>(at - m_buffer) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SmallStringBase::rfind(char c, u32 offset) const
|
||||||
|
{
|
||||||
|
if (m_length == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DebugAssert(offset <= m_length);
|
||||||
|
const char* at = std::strrchr(m_buffer + offset, c);
|
||||||
|
return at ? static_cast<s32>(at - m_buffer) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SmallStringBase::find(const char* str, u32 offset) const
|
||||||
|
{
|
||||||
|
if (m_length == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DebugAssert(offset <= m_length);
|
||||||
|
const char* at = std::strstr(m_buffer + offset, str);
|
||||||
|
return at ? static_cast<s32>(at - m_buffer) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::resize(u32 new_size, char fill, bool shrink_if_smaller)
|
||||||
|
{
|
||||||
|
// if going larger, or we don't own the buffer, realloc
|
||||||
|
if (new_size >= m_buffer_size)
|
||||||
|
{
|
||||||
|
reserve(new_size);
|
||||||
|
|
||||||
|
if (m_length < new_size)
|
||||||
|
{
|
||||||
|
std::memset(m_buffer + m_length, fill, m_buffer_size - m_length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_length = new_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update length and terminator
|
||||||
|
#if _DEBUG
|
||||||
|
std::memset(m_buffer + new_size, 0, m_buffer_size - new_size);
|
||||||
|
#else
|
||||||
|
m_buffer[new_size] = 0;
|
||||||
|
#endif
|
||||||
|
m_length = new_size;
|
||||||
|
|
||||||
|
// shrink if requested
|
||||||
|
if (shrink_if_smaller)
|
||||||
|
shrink_to_fit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::update_size()
|
||||||
|
{
|
||||||
|
m_length = static_cast<u32>(std::strlen(m_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view SmallStringBase::substr(s32 offset, s32 count) const
|
||||||
|
{
|
||||||
|
// calc real offset
|
||||||
|
u32 real_offset;
|
||||||
|
if (offset < 0)
|
||||||
|
real_offset = static_cast<u32>(std::max<s32>(0, static_cast<s32>(m_length + offset)));
|
||||||
|
else
|
||||||
|
real_offset = std::min((u32)offset, m_length);
|
||||||
|
|
||||||
|
// calc real count
|
||||||
|
u32 real_count;
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
real_count =
|
||||||
|
std::min(m_length - real_offset, static_cast<u32>(std::max<s32>(0, static_cast<s32>(m_length) + count)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
real_count = std::min(m_length - real_offset, static_cast<u32>(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (real_count > 0) ? std::string_view(m_buffer + real_offset, real_count) : std::string_view();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmallStringBase::erase(s32 offset, s32 count)
|
||||||
|
{
|
||||||
|
// calc real offset
|
||||||
|
u32 real_offset;
|
||||||
|
if (offset < 0)
|
||||||
|
real_offset = static_cast<u32>(std::max<s32>(0, static_cast<s32>(m_length + offset)));
|
||||||
|
else
|
||||||
|
real_offset = std::min((u32)offset, m_length);
|
||||||
|
|
||||||
|
// calc real count
|
||||||
|
u32 real_count;
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
real_count =
|
||||||
|
std::min(m_length - real_offset, static_cast<u32>(std::max<s32>(0, static_cast<s32>(m_length) + count)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
real_count = std::min(m_length - real_offset, static_cast<u32>(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fastpath: offset == 0, count < 0, wipe whole string.
|
||||||
|
if (real_offset == 0 && real_count == m_length)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fastpath: offset >= 0, count < 0, wipe everything after offset + count
|
||||||
|
if ((real_offset + real_count) == m_length)
|
||||||
|
{
|
||||||
|
m_length -= real_count;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::memset(m_buffer + m_length, 0, m_buffer_size - m_length);
|
||||||
|
#else
|
||||||
|
m_buffer[m_length] = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// Slowpath: offset >= 0, count < length
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const u32 after_erase_block = m_length - real_offset - real_count;
|
||||||
|
DebugAssert(after_erase_block > 0);
|
||||||
|
|
||||||
|
std::memmove(m_buffer + offset, m_buffer + real_offset + real_count, after_erase_block);
|
||||||
|
m_length = m_length - real_count;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::memset(m_buffer + m_length, 0, m_buffer_size - m_length);
|
||||||
|
#else
|
||||||
|
m_buffer[m_length] = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
343
src/common/small_string.h
Normal file
343
src/common/small_string.h
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
//
|
||||||
|
// SmallString
|
||||||
|
// Lightweight string class which can be allocated on the stack, instead of with heap allocations.
|
||||||
|
//
|
||||||
|
class SmallStringBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = char;
|
||||||
|
|
||||||
|
SmallStringBase();
|
||||||
|
SmallStringBase(const char* str);
|
||||||
|
SmallStringBase(const char* str, u32 length);
|
||||||
|
SmallStringBase(const SmallStringBase& copy);
|
||||||
|
SmallStringBase(SmallStringBase&& move);
|
||||||
|
SmallStringBase(const std::string& str);
|
||||||
|
SmallStringBase(const std::string_view& sv);
|
||||||
|
|
||||||
|
// Destructor. Child classes may not have any destructors, as this is not virtual.
|
||||||
|
~SmallStringBase();
|
||||||
|
|
||||||
|
// manual assignment
|
||||||
|
void assign(const char* str);
|
||||||
|
void assign(const char* str, u32 length);
|
||||||
|
void assign(const std::string& copy);
|
||||||
|
void assign(const std::string_view& copy);
|
||||||
|
void assign(const SmallStringBase& copy);
|
||||||
|
void assign(SmallStringBase&& move);
|
||||||
|
|
||||||
|
// Ensures that we have space bytes free in the buffer.
|
||||||
|
void make_room_for(u32 space);
|
||||||
|
|
||||||
|
// clears the contents of the string
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// append a single character to this string
|
||||||
|
void append(char c);
|
||||||
|
|
||||||
|
// append a string to this string
|
||||||
|
void append(const char* appendText);
|
||||||
|
void append(const char* str, u32 length);
|
||||||
|
void append(const std::string& str);
|
||||||
|
void append(const std::string_view& str);
|
||||||
|
void append(const SmallStringBase& str);
|
||||||
|
|
||||||
|
// append formatted string to this string
|
||||||
|
void append_format(const char* format, ...) printflike(2, 3);
|
||||||
|
void append_format_va(const char* format, va_list ap);
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
void append_fmt(fmt::format_string<T...> fmt, T&&... args);
|
||||||
|
|
||||||
|
// append a single character to this string
|
||||||
|
void prepend(char c);
|
||||||
|
|
||||||
|
// append a string to this string
|
||||||
|
void prepend(const char* str);
|
||||||
|
void prepend(const char* str, u32 length);
|
||||||
|
void prepend(const std::string& str);
|
||||||
|
void prepend(const std::string_view& str);
|
||||||
|
void prepend(const SmallStringBase& str);
|
||||||
|
|
||||||
|
// append formatted string to this string
|
||||||
|
void prepend_format(const char* format, ...) printflike(2, 3);
|
||||||
|
void prepend_format_va(const char* format, va_list ap);
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
void prepend_fmt(fmt::format_string<T...> fmt, T&&... args);
|
||||||
|
|
||||||
|
// insert a string at the specified offset
|
||||||
|
void insert(s32 offset, const char* str);
|
||||||
|
void insert(s32 offset, const char* str, u32 length);
|
||||||
|
void insert(s32 offset, const std::string& str);
|
||||||
|
void insert(s32 offset, const std::string_view& str);
|
||||||
|
void insert(s32 offset, const SmallStringBase& str);
|
||||||
|
|
||||||
|
// set to formatted string
|
||||||
|
void format(const char* format, ...) printflike(2, 3);
|
||||||
|
void format_va(const char* format, va_list ap);
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
void fmt(fmt::format_string<T...> fmt, T&&... args);
|
||||||
|
|
||||||
|
// compare one string to another
|
||||||
|
bool equals(const char* str) const;
|
||||||
|
bool equals(const SmallStringBase& str) const;
|
||||||
|
bool equals(const std::string_view& str) const;
|
||||||
|
bool iequals(const char* str) const;
|
||||||
|
bool iequals(const SmallStringBase& str) const;
|
||||||
|
bool iequals(const std::string_view& str) const;
|
||||||
|
|
||||||
|
// numerical compares
|
||||||
|
int compare(const char* str) const;
|
||||||
|
int compare(const SmallStringBase& str) const;
|
||||||
|
int compare(const std::string_view& str) const;
|
||||||
|
int icompare(const char* str) const;
|
||||||
|
int icompare(const SmallStringBase& str) const;
|
||||||
|
int icompare(const std::string_view& str) const;
|
||||||
|
|
||||||
|
// starts with / ends with
|
||||||
|
bool starts_with(const char* str, bool case_sensitive = true) const;
|
||||||
|
bool starts_with(const std::string_view& str, bool case_sensitive = true) const;
|
||||||
|
bool starts_with(const SmallStringBase& str, bool case_sensitive = true) const;
|
||||||
|
bool ends_with(const char* str, bool case_sensitive = true) const;
|
||||||
|
bool ends_with(const std::string_view& str, bool case_sensitive = true) const;
|
||||||
|
bool ends_with(const SmallStringBase& str, bool case_sensitive = true) const;
|
||||||
|
|
||||||
|
// searches for a character inside a string
|
||||||
|
// rfind is the same except it starts at the end instead of the start
|
||||||
|
// returns -1 if it is not found, otherwise the offset in the string
|
||||||
|
s32 find(char c, u32 offset = 0) const;
|
||||||
|
s32 rfind(char c, u32 offset = 0) const;
|
||||||
|
|
||||||
|
// searches for a string inside a string
|
||||||
|
// rfind is the same except it starts at the end instead of the start
|
||||||
|
// returns -1 if it is not found, otherwise the offset in the string
|
||||||
|
s32 find(const char* str, u32 offset = 0) const;
|
||||||
|
|
||||||
|
// removes characters from string
|
||||||
|
void erase(s32 offset, s32 count = std::numeric_limits<s32>::max());
|
||||||
|
|
||||||
|
// alters the length of the string to be at least len bytes long
|
||||||
|
void reserve(u32 new_reserve);
|
||||||
|
|
||||||
|
// Cuts characters off the string to reduce it to len bytes long.
|
||||||
|
void resize(u32 new_size, char fill = ' ', bool shrink_if_smaller = false);
|
||||||
|
|
||||||
|
// updates the internal length counter when the string is externally modified
|
||||||
|
void update_size();
|
||||||
|
|
||||||
|
// shrink the string to the minimum size possible
|
||||||
|
void shrink_to_fit();
|
||||||
|
|
||||||
|
// gets the size of the string
|
||||||
|
ALWAYS_INLINE u32 length() const { return m_length; }
|
||||||
|
ALWAYS_INLINE bool empty() const { return (m_length == 0); }
|
||||||
|
|
||||||
|
// gets the maximum number of bytes we can write to the string, currently
|
||||||
|
ALWAYS_INLINE u32 buffer_size() const { return m_buffer_size; }
|
||||||
|
|
||||||
|
// gets a constant pointer to the C string
|
||||||
|
ALWAYS_INLINE const char* c_str() const { return m_buffer; }
|
||||||
|
|
||||||
|
// gets a writable char array, do not write more than reserve characters to it.
|
||||||
|
ALWAYS_INLINE char* data() { return m_buffer; }
|
||||||
|
|
||||||
|
// returns the end of the string (pointer is past the last character)
|
||||||
|
ALWAYS_INLINE const char* end_ptr() const { return m_buffer + m_length; }
|
||||||
|
|
||||||
|
// STL adapters
|
||||||
|
ALWAYS_INLINE void push_back(value_type&& val) { append(val); }
|
||||||
|
|
||||||
|
// returns a string view for this string
|
||||||
|
std::string_view view() const;
|
||||||
|
|
||||||
|
// returns a substring view for this string
|
||||||
|
std::string_view substr(s32 offset, s32 count) const;
|
||||||
|
|
||||||
|
// accessor operators
|
||||||
|
ALWAYS_INLINE operator const char*() const { return c_str(); }
|
||||||
|
ALWAYS_INLINE operator char*() { return data(); }
|
||||||
|
ALWAYS_INLINE operator std::string_view() const { return view(); }
|
||||||
|
|
||||||
|
// comparative operators
|
||||||
|
ALWAYS_INLINE bool operator==(const char* str) const { return equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator==(const SmallStringBase& str) const { return equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator==(const std::string_view& str) const { return equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator!=(const char* str) const { return !equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator!=(const SmallStringBase& str) const { return !equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator!=(const std::string_view& str) const { return !equals(str); }
|
||||||
|
ALWAYS_INLINE bool operator<(const char* str) const { return (compare(str) < 0); }
|
||||||
|
ALWAYS_INLINE bool operator<(const SmallStringBase& str) const { return (compare(str) < 0); }
|
||||||
|
ALWAYS_INLINE bool operator<(const std::string_view& str) const { return (compare(str) < 0); }
|
||||||
|
ALWAYS_INLINE bool operator>(const char* str) const { return (compare(str) > 0); }
|
||||||
|
ALWAYS_INLINE bool operator>(const SmallStringBase& str) const { return (compare(str) > 0); }
|
||||||
|
ALWAYS_INLINE bool operator>(const std::string_view& str) const { return (compare(str) > 0); }
|
||||||
|
|
||||||
|
SmallStringBase& operator=(const SmallStringBase& copy);
|
||||||
|
SmallStringBase& operator=(const char* str);
|
||||||
|
SmallStringBase& operator=(const std::string& str);
|
||||||
|
SmallStringBase& operator=(const std::string_view& str);
|
||||||
|
SmallStringBase& operator=(SmallStringBase&& move);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Pointer to memory where the string is located
|
||||||
|
char* m_buffer = nullptr;
|
||||||
|
|
||||||
|
// Length of the string located in pBuffer (in characters)
|
||||||
|
u32 m_length = 0;
|
||||||
|
|
||||||
|
// Size of the buffer pointed to by pBuffer
|
||||||
|
u32 m_buffer_size = 0;
|
||||||
|
|
||||||
|
// True if the string is dynamically allocated on the heap.
|
||||||
|
bool m_on_heap = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// stack-allocated string
|
||||||
|
template<u32 L>
|
||||||
|
class SmallStackString : public SmallStringBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE SmallStackString() { init(); }
|
||||||
|
|
||||||
|
ALWAYS_INLINE SmallStackString(const char* str)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
assign(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE SmallStackString(const char* str, u32 length)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
assign(str, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE SmallStackString(const SmallStringBase& copy)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
assign(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE SmallStackString(SmallStringBase&& move)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
assign(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE SmallStackString(const std::string_view& sv)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
assign(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the fromstring method
|
||||||
|
static SmallStackString from_format(const char* format, ...) printflike(1, 2);
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
static SmallStackString from_fmt(fmt::format_string<T...> fmt, T&&... args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char m_stack_buffer[L + 1];
|
||||||
|
|
||||||
|
ALWAYS_INLINE void init()
|
||||||
|
{
|
||||||
|
m_buffer = m_stack_buffer;
|
||||||
|
m_buffer_size = L + 1;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::memset(m_stack_buffer, 0, sizeof(m_stack_buffer));
|
||||||
|
#else
|
||||||
|
m_stack_buffer[0] = '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4459) // warning C4459: declaration of 'uint' hides global declaration
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<u32 L>
|
||||||
|
ALWAYS_INLINE SmallStackString<L> SmallStackString<L>::from_format(const char* format, ...)
|
||||||
|
{
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
|
||||||
|
SmallStackString ret;
|
||||||
|
ret.format_va(format, ap);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<u32 L>
|
||||||
|
template<typename... T>
|
||||||
|
ALWAYS_INLINE SmallStackString<L> SmallStackString<L>::from_fmt(fmt::format_string<T...> fmt, T&&... args)
|
||||||
|
{
|
||||||
|
SmallStackString<L> ret;
|
||||||
|
fmt::vformat_to(std::back_inserter(ret), fmt, fmt::make_format_args(args...));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stack string types
|
||||||
|
using TinyString = SmallStackString<64>;
|
||||||
|
using SmallString = SmallStackString<256>;
|
||||||
|
using LargeString = SmallStackString<512>;
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
ALWAYS_INLINE void SmallStringBase::append_fmt(fmt::format_string<T...> fmt, T&&... args)
|
||||||
|
{
|
||||||
|
fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
ALWAYS_INLINE void SmallStringBase::prepend_fmt(fmt::format_string<T...> fmt, T&&... args)
|
||||||
|
{
|
||||||
|
TinyString str;
|
||||||
|
fmt::vformat_to(std::back_inserter(str), fmt, fmt::make_format_args(args...));
|
||||||
|
prepend(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
ALWAYS_INLINE void SmallStringBase::fmt(fmt::format_string<T...> fmt, T&&... args)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct fmt::formatter<SmallStringBase>
|
||||||
|
{
|
||||||
|
template<typename ParseContext>
|
||||||
|
constexpr auto parse(ParseContext& ctx)
|
||||||
|
{
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(const SmallStringBase& str, FormatContext& ctx)
|
||||||
|
{
|
||||||
|
return fmt::format_to(ctx.out(), "{}", str.view());
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load diff
|
@ -1,472 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "fmt/core.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <cstring>
|
|
||||||
#include <limits>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
//
|
|
||||||
// String
|
|
||||||
// Implements a UTF-8 string container with copy-on-write behavior.
|
|
||||||
// The data class is not currently threadsafe (creating a mutex on each container would be overkill),
|
|
||||||
// so locking is still required when multiple threads are involved.
|
|
||||||
//
|
|
||||||
class String
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Internal StringData class.
|
|
||||||
struct StringData
|
|
||||||
{
|
|
||||||
// Pointer to memory where the string is located
|
|
||||||
char* pBuffer;
|
|
||||||
|
|
||||||
// Length of the string located in pBuffer (in characters)
|
|
||||||
u32 StringLength;
|
|
||||||
|
|
||||||
// Size of the buffer pointed to by pBuffer
|
|
||||||
u32 BufferSize;
|
|
||||||
|
|
||||||
// Reference count of this data object. If set to -1,
|
|
||||||
// it is considered noncopyable and any copies of the string
|
|
||||||
// will always create their own copy.
|
|
||||||
s32 ReferenceCount;
|
|
||||||
|
|
||||||
// Whether the memory pointed to by pBuffer is writable.
|
|
||||||
bool ReadOnly;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = char;
|
|
||||||
|
|
||||||
// Creates an empty string.
|
|
||||||
String();
|
|
||||||
|
|
||||||
// Creates a string containing the specified text.
|
|
||||||
// Note that this will incur a heap allocation, even if Text is on the stack.
|
|
||||||
// For strings that do not allocate any space on the heap, see StaticString.
|
|
||||||
String(const char* Text);
|
|
||||||
|
|
||||||
// Creates a string contained the specified text (with length).
|
|
||||||
String(const char* Text, u32 Count);
|
|
||||||
|
|
||||||
// Creates a string using the same buffer as another string (copy-on-write).
|
|
||||||
String(const String& copyString);
|
|
||||||
|
|
||||||
// Move constructor, take reference from other string.
|
|
||||||
String(String&& moveString);
|
|
||||||
|
|
||||||
// Construct a string from a data object, does not increment the reference count on the string data, use carefully.
|
|
||||||
explicit String(StringData* pStringData) : m_pStringData(pStringData) {}
|
|
||||||
|
|
||||||
// Creates string from string_view.
|
|
||||||
String(const std::string_view& sv);
|
|
||||||
|
|
||||||
// Destructor. Child classes may not have any destructors, as this is not virtual.
|
|
||||||
~String();
|
|
||||||
|
|
||||||
// manual assignment
|
|
||||||
void Assign(const String& copyString);
|
|
||||||
void Assign(const char* copyText);
|
|
||||||
void Assign(const std::string& copyString);
|
|
||||||
void Assign(const std::string_view& copyString);
|
|
||||||
void Assign(String&& moveString);
|
|
||||||
|
|
||||||
// assignment but ensures that we have our own copy.
|
|
||||||
void AssignCopy(const String& copyString);
|
|
||||||
|
|
||||||
// Ensures that the string has its own unique copy of the data.
|
|
||||||
void EnsureOwnWritableCopy();
|
|
||||||
|
|
||||||
// Ensures that we have our own copy of the buffer, and spaceRequired bytes free in the buffer.
|
|
||||||
void EnsureRemainingSpace(u32 spaceRequired);
|
|
||||||
|
|
||||||
// clears the contents of the string
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
// clear the contents of the string, and free any memory currently being used
|
|
||||||
void Obliterate();
|
|
||||||
|
|
||||||
// swaps strings
|
|
||||||
void Swap(String& swapString);
|
|
||||||
|
|
||||||
// append a single character to this string
|
|
||||||
void AppendCharacter(char c);
|
|
||||||
|
|
||||||
// append a string to this string
|
|
||||||
void AppendString(const String& appendStr);
|
|
||||||
void AppendString(const char* appendText);
|
|
||||||
void AppendString(const char* appendString, u32 Count);
|
|
||||||
void AppendString(const std::string& appendString);
|
|
||||||
void AppendString(const std::string_view& appendString);
|
|
||||||
|
|
||||||
// append a substring of the specified string to this string
|
|
||||||
void AppendSubString(const String& appendStr, s32 Offset = 0, s32 Count = std::numeric_limits<s32>::max());
|
|
||||||
void AppendSubString(const char* appendText, s32 Offset = 0, s32 Count = std::numeric_limits<s32>::max());
|
|
||||||
|
|
||||||
// append formatted string to this string
|
|
||||||
void AppendFormattedString(const char* FormatString, ...) printflike(2, 3);
|
|
||||||
void AppendFormattedStringVA(const char* FormatString, va_list ArgPtr);
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void AppendFmtString(fmt::format_string<T...> fmt, T&&... args);
|
|
||||||
|
|
||||||
// append a single character to this string
|
|
||||||
void PrependCharacter(char c);
|
|
||||||
|
|
||||||
// append a string to this string
|
|
||||||
void PrependString(const String& appendStr);
|
|
||||||
void PrependString(const char* appendText);
|
|
||||||
void PrependString(const char* appendString, u32 Count);
|
|
||||||
void PrependString(const std::string& appendStr);
|
|
||||||
void PrependString(const std::string_view& appendStr);
|
|
||||||
|
|
||||||
// append a substring of the specified string to this string
|
|
||||||
void PrependSubString(const String& appendStr, s32 Offset = 0, s32 Count = std::numeric_limits<s32>::max());
|
|
||||||
void PrependSubString(const char* appendText, s32 Offset = 0, s32 Count = std::numeric_limits<s32>::max());
|
|
||||||
|
|
||||||
// append formatted string to this string
|
|
||||||
void PrependFormattedString(const char* FormatString, ...) printflike(2, 3);
|
|
||||||
void PrependFormattedStringVA(const char* FormatString, va_list ArgPtr);
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void PrependFmtString(fmt::format_string<T...> fmt, T&&... args);
|
|
||||||
|
|
||||||
// insert a string at the specified offset
|
|
||||||
void InsertString(s32 offset, const String& appendStr);
|
|
||||||
void InsertString(s32 offset, const char* appendStr);
|
|
||||||
void InsertString(s32 offset, const char* appendStr, u32 appendStrLength);
|
|
||||||
void InsertString(s32 offset, const std::string& appendStr);
|
|
||||||
void InsertString(s32 offset, const std::string_view& appendStr);
|
|
||||||
|
|
||||||
// set to formatted string
|
|
||||||
void Format(const char* FormatString, ...) printflike(2, 3);
|
|
||||||
void FormatVA(const char* FormatString, va_list ArgPtr);
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void Fmt(fmt::format_string<T...> fmt, T&&... args);
|
|
||||||
|
|
||||||
// compare one string to another
|
|
||||||
bool Compare(const String& otherString) const;
|
|
||||||
bool Compare(const char* otherText) const;
|
|
||||||
bool SubCompare(const String& otherString, u32 Length) const;
|
|
||||||
bool SubCompare(const char* otherText, u32 Length) const;
|
|
||||||
bool CompareInsensitive(const String& otherString) const;
|
|
||||||
bool CompareInsensitive(const char* otherText) const;
|
|
||||||
bool SubCompareInsensitive(const String& otherString, u32 Length) const;
|
|
||||||
bool SubCompareInsensitive(const char* otherText, u32 Length) const;
|
|
||||||
|
|
||||||
// numerical compares
|
|
||||||
int NumericCompare(const String& otherString) const;
|
|
||||||
int NumericCompare(const char* otherText) const;
|
|
||||||
int NumericCompareInsensitive(const String& otherString) const;
|
|
||||||
int NumericCompareInsensitive(const char* otherText) const;
|
|
||||||
|
|
||||||
// starts with / ends with
|
|
||||||
bool StartsWith(const char* compareString, bool caseSensitive = true) const;
|
|
||||||
bool StartsWith(const String& compareString, bool caseSensitive = true) const;
|
|
||||||
bool EndsWith(const char* compareString, bool caseSensitive = true) const;
|
|
||||||
bool EndsWith(const String& compareString, bool caseSensitive = true) const;
|
|
||||||
|
|
||||||
// searches for a character inside a string
|
|
||||||
// rfind is the same except it starts at the end instead of the start
|
|
||||||
// returns -1 if it is not found, otherwise the offset in the string
|
|
||||||
s32 Find(char c, u32 Offset = 0) const;
|
|
||||||
s32 RFind(char c, u32 Offset = 0) const;
|
|
||||||
|
|
||||||
// searches for a string inside a string
|
|
||||||
// rfind is the same except it starts at the end instead of the start
|
|
||||||
// returns -1 if it is not found, otherwise the offset in the string
|
|
||||||
s32 Find(const char* str, u32 Offset = 0) const;
|
|
||||||
|
|
||||||
// alters the length of the string to be at least len bytes long
|
|
||||||
void Reserve(u32 newReserve, bool Force = false);
|
|
||||||
|
|
||||||
// Cuts characters off the string to reduce it to len bytes long.
|
|
||||||
void Resize(u32 newSize, char fillerCharacter = ' ', bool skrinkIfSmaller = false);
|
|
||||||
|
|
||||||
// updates the internal length counter when the string is externally modified
|
|
||||||
void UpdateSize();
|
|
||||||
|
|
||||||
// shrink the string to the minimum size possible
|
|
||||||
void Shrink(bool Force = false);
|
|
||||||
|
|
||||||
// gets the size of the string
|
|
||||||
u32 GetLength() const { return m_pStringData->StringLength; }
|
|
||||||
bool IsEmpty() const { return (m_pStringData->StringLength == 0); }
|
|
||||||
|
|
||||||
// gets the maximum number of bytes we can write to the string, currently
|
|
||||||
u32 GetBufferSize() const { return m_pStringData->BufferSize; }
|
|
||||||
u32 GetWritableBufferSize()
|
|
||||||
{
|
|
||||||
EnsureOwnWritableCopy();
|
|
||||||
return m_pStringData->BufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates a new string using part of this string
|
|
||||||
String SubString(s32 Offset, s32 Count = std::numeric_limits<s32>::max()) const;
|
|
||||||
|
|
||||||
// erase count characters at offset from this string. if count is less than zero, everything past offset is erased
|
|
||||||
void Erase(s32 Offset, s32 Count = std::numeric_limits<s32>::max());
|
|
||||||
|
|
||||||
// replaces all instances of character c with character r in this string
|
|
||||||
// returns the number of changes
|
|
||||||
u32 Replace(char searchCharacter, char replaceCharacter);
|
|
||||||
|
|
||||||
// replaces all instances of string s with string r in this string
|
|
||||||
// returns the number of changes
|
|
||||||
u32 Replace(const char* searchString, const char* replaceString);
|
|
||||||
|
|
||||||
// convert string to lowercase
|
|
||||||
void ToLower();
|
|
||||||
|
|
||||||
// convert string to upper
|
|
||||||
void ToUpper();
|
|
||||||
|
|
||||||
// strip characters from start and end of the string
|
|
||||||
void LStrip(const char* szStripCharacters = " \t\r\n");
|
|
||||||
void RStrip(const char* szStripCharacters = " \t\r\n");
|
|
||||||
void Strip(const char* szStripCharacters = " \t\r\n");
|
|
||||||
|
|
||||||
// gets a constant pointer to the string
|
|
||||||
const char* GetCharArray() const { return m_pStringData->pBuffer; }
|
|
||||||
|
|
||||||
// gets a writable char array, do not write more than reserve characters to it.
|
|
||||||
char* GetWriteableCharArray()
|
|
||||||
{
|
|
||||||
EnsureOwnWritableCopy();
|
|
||||||
return m_pStringData->pBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a string view for this string
|
|
||||||
std::string_view GetStringView() const
|
|
||||||
{
|
|
||||||
return IsEmpty() ? std::string_view() : std::string_view(GetCharArray(), GetLength());
|
|
||||||
}
|
|
||||||
std::string ToStdString() const
|
|
||||||
{
|
|
||||||
return std::string(GetStringView());
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates a new string from the specified format
|
|
||||||
static String FromFormat(const char* FormatString, ...) printflike(1, 2);
|
|
||||||
|
|
||||||
// accessor operators
|
|
||||||
// const char &operator[](u32 i) const { DebugAssert(i < m_pStringData->StringLength); return
|
|
||||||
// m_pStringData->pBuffer[i]; } char &operator[](u32 i) { DebugAssert(i < m_pStringData->StringLength); return
|
|
||||||
// m_pStringData->pBuffer[i]; }
|
|
||||||
operator const char*() const { return GetCharArray(); }
|
|
||||||
operator char*() { return GetWriteableCharArray(); }
|
|
||||||
operator std::string_view() const { return GetStringView(); }
|
|
||||||
|
|
||||||
// Will use the string data provided.
|
|
||||||
String& operator=(const String& copyString)
|
|
||||||
{
|
|
||||||
Assign(copyString);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocates own buffer and copies text.
|
|
||||||
String& operator=(const char* Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
String& operator=(const std::string& Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
String& operator=(const std::string_view& Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move operator.
|
|
||||||
String& operator=(String&& moveString)
|
|
||||||
{
|
|
||||||
Assign(moveString);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// comparative operators
|
|
||||||
bool operator==(const String& compString) const { return Compare(compString); }
|
|
||||||
bool operator==(const char* compString) const { return Compare(compString); }
|
|
||||||
bool operator!=(const String& compString) const { return !Compare(compString); }
|
|
||||||
bool operator!=(const char* compString) const { return !Compare(compString); }
|
|
||||||
bool operator<(const String& compString) const { return (NumericCompare(compString) < 0); }
|
|
||||||
bool operator<(const char* compString) const { return (NumericCompare(compString) < 0); }
|
|
||||||
bool operator>(const String& compString) const { return (NumericCompare(compString) > 0); }
|
|
||||||
bool operator>(const char* compString) const { return (NumericCompare(compString) > 0); }
|
|
||||||
|
|
||||||
// STL adapters
|
|
||||||
ALWAYS_INLINE void push_back(value_type&& val) { AppendCharacter(val); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Internal append function.
|
|
||||||
void InternalPrepend(const char* pString, u32 Length);
|
|
||||||
void InternalAppend(const char* pString, u32 Length);
|
|
||||||
|
|
||||||
// Pointer to string data.
|
|
||||||
StringData* m_pStringData;
|
|
||||||
|
|
||||||
// Empty string data.
|
|
||||||
static const StringData s_EmptyStringData;
|
|
||||||
};
|
|
||||||
|
|
||||||
// static string, stored in .rodata
|
|
||||||
#define StaticString(Text) \
|
|
||||||
[]() noexcept -> String { \
|
|
||||||
static constexpr u32 buffer_size = sizeof(Text); \
|
|
||||||
static constexpr u32 length = buffer_size - 1; \
|
|
||||||
static constexpr String::StringData data{const_cast<char*>(Text), length, buffer_size, static_cast<s32>(-1), \
|
|
||||||
true}; \
|
|
||||||
return String(const_cast<String::StringData*>(&data)); \
|
|
||||||
}()
|
|
||||||
|
|
||||||
// stack-allocated string
|
|
||||||
template<u32 L>
|
|
||||||
class StackString : public String
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StackString() : String(&m_sStringData) { InitStackStringData(); }
|
|
||||||
|
|
||||||
StackString(const char* Text) : String(&m_sStringData)
|
|
||||||
{
|
|
||||||
InitStackStringData();
|
|
||||||
Assign(Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
StackString(const char* Text, u32 Count) : String(&m_sStringData)
|
|
||||||
{
|
|
||||||
InitStackStringData();
|
|
||||||
AppendString(Text, Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
StackString(const String& copyString) : String(&m_sStringData)
|
|
||||||
{
|
|
||||||
// force a copy by passing it a string pointer, instead of a string object
|
|
||||||
InitStackStringData();
|
|
||||||
Assign(copyString.GetCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
StackString(const StackString& copyString) : String(&m_sStringData)
|
|
||||||
{
|
|
||||||
// force a copy by passing it a string pointer, instead of a string object
|
|
||||||
InitStackStringData();
|
|
||||||
Assign(copyString.GetCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
StackString(const std::string_view& sv) : String(&m_sStringData)
|
|
||||||
{
|
|
||||||
InitStackStringData();
|
|
||||||
AppendString(sv.data(), static_cast<u32>(sv.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the fromstring method
|
|
||||||
static StackString FromFormat(const char* FormatString, ...) printflike(1, 2)
|
|
||||||
{
|
|
||||||
va_list argPtr;
|
|
||||||
va_start(argPtr, FormatString);
|
|
||||||
|
|
||||||
StackString returnValue;
|
|
||||||
returnValue.FormatVA(FormatString, argPtr);
|
|
||||||
|
|
||||||
va_end(argPtr);
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
static StackString FromFmt(fmt::format_string<T...> fmt, T&&... args)
|
|
||||||
{
|
|
||||||
StackString ret;
|
|
||||||
fmt::vformat_to(std::back_inserter(ret), fmt, fmt::make_format_args(args...));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Will use the string data provided.
|
|
||||||
StackString& operator=(const StackString& copyString)
|
|
||||||
{
|
|
||||||
Assign(copyString.GetCharArray());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
StackString& operator=(const String& copyString)
|
|
||||||
{
|
|
||||||
Assign(copyString.GetCharArray());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocates own buffer and copies text.
|
|
||||||
StackString& operator=(const char* Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
StackString& operator=(const std::string& Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
StackString& operator=(const std::string_view& Text)
|
|
||||||
{
|
|
||||||
Assign(Text);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
StringData m_sStringData;
|
|
||||||
char m_strStackBuffer[L + 1];
|
|
||||||
|
|
||||||
inline void InitStackStringData()
|
|
||||||
{
|
|
||||||
m_sStringData.pBuffer = m_strStackBuffer;
|
|
||||||
m_sStringData.StringLength = 0;
|
|
||||||
m_sStringData.BufferSize = countof(m_strStackBuffer);
|
|
||||||
m_sStringData.ReadOnly = false;
|
|
||||||
m_sStringData.ReferenceCount = -1;
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
std::memset(m_strStackBuffer, 0, sizeof(m_strStackBuffer));
|
|
||||||
#else
|
|
||||||
m_strStackBuffer[0] = '\0';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// stack string types
|
|
||||||
typedef StackString<64> TinyString;
|
|
||||||
typedef StackString<256> SmallString;
|
|
||||||
typedef StackString<512> LargeString;
|
|
||||||
typedef StackString<512> PathString;
|
|
||||||
|
|
||||||
// empty string global
|
|
||||||
extern const String EmptyString;
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void String::AppendFmtString(fmt::format_string<T...> fmt, T&&... args)
|
|
||||||
{
|
|
||||||
fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void String::PrependFmtString(fmt::format_string<T...> fmt, T&&... args)
|
|
||||||
{
|
|
||||||
TinyString str;
|
|
||||||
fmt::vformat_to(std::back_inserter(str), fmt, fmt::make_format_args(args...));
|
|
||||||
PrependString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
void String::Fmt(fmt::format_string<T...> fmt, T&&... args)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...));
|
|
||||||
}
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "util/cd_image.h"
|
#include "util/cd_image.h"
|
||||||
|
@ -253,7 +253,7 @@ void Achievements::ReportRCError(int err, fmt::format_string<T...> fmt, T&&... a
|
||||||
{
|
{
|
||||||
TinyString str;
|
TinyString str;
|
||||||
fmt::vformat_to(std::back_inserter(str), fmt, fmt::make_format_args(args...));
|
fmt::vformat_to(std::back_inserter(str), fmt, fmt::make_format_args(args...));
|
||||||
str.AppendFmtString("{} ({})", rc_error_str(err), err);
|
str.append_fmt("{} ({})", rc_error_str(err), err);
|
||||||
ReportError(str);
|
ReportError(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1137,16 +1137,15 @@ void Achievements::HandleLeaderboardTrackerShowEvent(const rc_client_event_t* ev
|
||||||
event->leaderboard_tracker->display);
|
event->leaderboard_tracker->display);
|
||||||
|
|
||||||
TinyString width_string;
|
TinyString width_string;
|
||||||
width_string.AppendString(ICON_FA_STOPWATCH);
|
width_string.append(ICON_FA_STOPWATCH);
|
||||||
const u32 display_len = static_cast<u32>(std::strlen(event->leaderboard_tracker->display));
|
const u32 display_len = static_cast<u32>(std::strlen(event->leaderboard_tracker->display));
|
||||||
for (u32 i = 0; i < display_len; i++)
|
for (u32 i = 0; i < display_len; i++)
|
||||||
width_string.AppendCharacter('0');
|
width_string.append('0');
|
||||||
|
|
||||||
LeaderboardTrackerIndicator indicator;
|
LeaderboardTrackerIndicator indicator;
|
||||||
indicator.tracker_id = event->leaderboard_tracker->id;
|
indicator.tracker_id = event->leaderboard_tracker->id;
|
||||||
indicator.size = ImGuiFullscreen::g_medium_font->CalcTextSizeA(
|
indicator.size = ImGuiFullscreen::g_medium_font->CalcTextSizeA(ImGuiFullscreen::g_medium_font->FontSize, FLT_MAX,
|
||||||
ImGuiFullscreen::g_medium_font->FontSize, FLT_MAX, 0.0f, width_string.GetCharArray(),
|
0.0f, width_string.c_str(), width_string.end_ptr());
|
||||||
width_string.GetCharArray() + width_string.GetLength());
|
|
||||||
indicator.text = fmt::format(ICON_FA_STOPWATCH " {}", event->leaderboard_tracker->display);
|
indicator.text = fmt::format(ICON_FA_STOPWATCH " {}", event->leaderboard_tracker->display);
|
||||||
indicator.active = true;
|
indicator.active = true;
|
||||||
s_active_leaderboard_trackers.push_back(std::move(indicator));
|
s_active_leaderboard_trackers.push_back(std::move(indicator));
|
||||||
|
@ -1495,8 +1494,8 @@ std::string Achievements::GetAchievementBadgePath(const rc_client_achievement_t*
|
||||||
if (achievement->badge_name[0] == 0)
|
if (achievement->badge_name[0] == 0)
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
path = Path::Combine(s_image_directory, TinyString::FromFmt("achievement_{}_{}_{}.png", s_game_id, achievement->id,
|
path = Path::Combine(s_image_directory, TinyString::from_fmt("achievement_{}_{}_{}.png", s_game_id, achievement->id,
|
||||||
s_achievement_state_strings[state]));
|
s_achievement_state_strings[state]));
|
||||||
|
|
||||||
if (!FileSystem::FileExists(path.c_str()))
|
if (!FileSystem::FileExists(path.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -1517,7 +1516,7 @@ std::string Achievements::GetUserBadgePath(const std::string_view& username)
|
||||||
std::string path;
|
std::string path;
|
||||||
const std::string clean_username = Path::SanitizeFileName(username);
|
const std::string clean_username = Path::SanitizeFileName(username);
|
||||||
if (!clean_username.empty())
|
if (!clean_username.empty())
|
||||||
path = Path::Combine(s_image_directory, TinyString::FromFmt("user_{}.png", clean_username));
|
path = Path::Combine(s_image_directory, TinyString::from_fmt("user_{}.png", clean_username));
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2062,27 +2061,27 @@ void Achievements::DrawAchievementsWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
||||||
text = s_game_title;
|
text.assign(s_game_title);
|
||||||
|
|
||||||
if (s_hardcore_mode)
|
if (s_hardcore_mode)
|
||||||
text.AppendString(TRANSLATE_SV("Achievements", " (Hardcore Mode)"));
|
text.append(TRANSLATE_SV("Achievements", " (Hardcore Mode)"));
|
||||||
|
|
||||||
top += g_large_font->FontSize + spacing;
|
top += g_large_font->FontSize + spacing;
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.GetCharArray(), text.GetCharArray() + text.GetLength(),
|
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
|
||||||
nullptr, ImVec2(0.0f, 0.0f), &title_bb);
|
&title_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + g_medium_font->FontSize));
|
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + g_medium_font->FontSize));
|
||||||
if (s_game_summary.num_unlocked_achievements == s_game_summary.num_core_achievements)
|
if (s_game_summary.num_unlocked_achievements == s_game_summary.num_core_achievements)
|
||||||
{
|
{
|
||||||
text.Fmt(TRANSLATE_FS("Achievements", "You have unlocked all achievements and earned {} points!"),
|
text.fmt(TRANSLATE_FS("Achievements", "You have unlocked all achievements and earned {} points!"),
|
||||||
s_game_summary.points_unlocked);
|
s_game_summary.points_unlocked);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text.Fmt(
|
text.fmt(
|
||||||
TRANSLATE_FS("Achievements", "You have unlocked {} of {} achievements, earning {} of {} possible points."),
|
TRANSLATE_FS("Achievements", "You have unlocked {} of {} achievements, earning {} of {} possible points."),
|
||||||
s_game_summary.num_unlocked_achievements, s_game_summary.num_core_achievements,
|
s_game_summary.num_unlocked_achievements, s_game_summary.num_core_achievements,
|
||||||
s_game_summary.points_unlocked, s_game_summary.points_core);
|
s_game_summary.points_unlocked, s_game_summary.points_core);
|
||||||
|
@ -2091,8 +2090,8 @@ void Achievements::DrawAchievementsWindow()
|
||||||
top += g_medium_font->FontSize + spacing;
|
top += g_medium_font->FontSize + spacing;
|
||||||
|
|
||||||
ImGui::PushFont(g_medium_font);
|
ImGui::PushFont(g_medium_font);
|
||||||
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.GetCharArray(),
|
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr,
|
||||||
text.GetCharArray() + text.GetLength(), nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
|
ImVec2(0.0f, 0.0f), &summary_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
const float progress_height = ImGuiFullscreen::LayoutScale(20.0f);
|
const float progress_height = ImGuiFullscreen::LayoutScale(20.0f);
|
||||||
|
@ -2104,14 +2103,13 @@ void Achievements::DrawAchievementsWindow()
|
||||||
ImVec2(progress_bb.Min.x + fraction * progress_bb.GetWidth(), progress_bb.Max.y),
|
ImVec2(progress_bb.Min.x + fraction * progress_bb.GetWidth(), progress_bb.Max.y),
|
||||||
ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
|
ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
|
||||||
|
|
||||||
text.Fmt("{}%", static_cast<int>(std::round(fraction * 100.0f)));
|
text.fmt("{}%", static_cast<int>(std::round(fraction * 100.0f)));
|
||||||
text_size = ImGui::CalcTextSize(text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
text_size = ImGui::CalcTextSize(text.c_str(), text.end_ptr());
|
||||||
const ImVec2 text_pos(progress_bb.Min.x + ((progress_bb.Max.x - progress_bb.Min.x) / 2.0f) - (text_size.x / 2.0f),
|
const ImVec2 text_pos(progress_bb.Min.x + ((progress_bb.Max.x - progress_bb.Min.x) / 2.0f) - (text_size.x / 2.0f),
|
||||||
progress_bb.Min.y + ((progress_bb.Max.y - progress_bb.Min.y) / 2.0f) -
|
progress_bb.Min.y + ((progress_bb.Max.y - progress_bb.Min.y) / 2.0f) -
|
||||||
(text_size.y / 2.0f));
|
(text_size.y / 2.0f));
|
||||||
dl->AddText(g_medium_font, g_medium_font->FontSize, text_pos,
|
dl->AddText(g_medium_font, g_medium_font->FontSize, text_pos,
|
||||||
ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryTextColor), text.GetCharArray(),
|
ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryTextColor), text.c_str(), text.end_ptr());
|
||||||
text.GetCharArray() + text.GetLength());
|
|
||||||
top += progress_height + spacing;
|
top += progress_height + spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2183,7 +2181,7 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
|
||||||
|
|
||||||
ImRect bb;
|
ImRect bb;
|
||||||
bool visible, hovered;
|
bool visible, hovered;
|
||||||
ImGuiFullscreen::MenuButtonFrame(TinyString::FromFmt("chv_{}", cheevo->id), true,
|
ImGuiFullscreen::MenuButtonFrame(TinyString::from_fmt("chv_{}", cheevo->id), true,
|
||||||
!is_measured ? ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT + unlock_size :
|
!is_measured ? ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT + unlock_size :
|
||||||
ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT +
|
ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT +
|
||||||
progress_height_unscaled + progress_spacing_unscaled,
|
progress_height_unscaled + progress_spacing_unscaled,
|
||||||
|
@ -2219,12 +2217,12 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
|
||||||
SmallString text;
|
SmallString text;
|
||||||
|
|
||||||
const float midpoint = bb.Min.y + g_large_font->FontSize + spacing;
|
const float midpoint = bb.Min.y + g_large_font->FontSize + spacing;
|
||||||
text.Fmt((cheevo->points != 1) ? TRANSLATE_FS("Achievements", "{} points") : TRANSLATE_FS("Achievements", "{} point"),
|
text.fmt((cheevo->points != 1) ? TRANSLATE_FS("Achievements", "{} points") : TRANSLATE_FS("Achievements", "{} point"),
|
||||||
cheevo->points);
|
cheevo->points);
|
||||||
const ImVec2 points_template_size(
|
const ImVec2 points_template_size(
|
||||||
g_medium_font->CalcTextSizeA(g_medium_font->FontSize, FLT_MAX, 0.0f, TRANSLATE("Achievements", "XXX points")));
|
g_medium_font->CalcTextSizeA(g_medium_font->FontSize, FLT_MAX, 0.0f, TRANSLATE("Achievements", "XXX points")));
|
||||||
const ImVec2 points_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, FLT_MAX, 0.0f, text.GetCharArray(),
|
const ImVec2 points_size(
|
||||||
text.GetCharArray() + text.GetLength()));
|
g_medium_font->CalcTextSizeA(g_medium_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr()));
|
||||||
const float points_template_start = bb.Max.x - points_template_size.x;
|
const float points_template_start = bb.Max.x - points_template_size.x;
|
||||||
const float points_start = points_template_start + ((points_template_size.x - points_size.x) * 0.5f);
|
const float points_start = points_template_start + ((points_template_size.x - points_size.x) * 0.5f);
|
||||||
const char* lock_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
|
const char* lock_text = is_unlocked ? ICON_FA_LOCK_OPEN : ICON_FA_LOCK;
|
||||||
|
@ -2248,18 +2246,18 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
|
||||||
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, cheevo->description, nullptr, nullptr, ImVec2(0.0f, 0.0f),
|
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, cheevo->description, nullptr, nullptr, ImVec2(0.0f, 0.0f),
|
||||||
&summary_bb);
|
&summary_bb);
|
||||||
}
|
}
|
||||||
ImGui::RenderTextClipped(points_bb.Min, points_bb.Max, text.GetCharArray(), text.GetCharArray() + text.GetLength(),
|
ImGui::RenderTextClipped(points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f),
|
||||||
&points_size, ImVec2(0.0f, 0.0f), &points_bb);
|
&points_bb);
|
||||||
|
|
||||||
if (is_unlocked)
|
if (is_unlocked)
|
||||||
{
|
{
|
||||||
TinyString date;
|
TinyString date;
|
||||||
FullscreenUI::TimeToPrintableString(&date, cheevo->unlock_time);
|
FullscreenUI::TimeToPrintableString(&date, cheevo->unlock_time);
|
||||||
text.Fmt(TRANSLATE_FS("Achievements", "Unlocked: {}"), date);
|
text.fmt(TRANSLATE_FS("Achievements", "Unlocked: {}"), date);
|
||||||
|
|
||||||
const ImRect unlock_bb(summary_bb.Min.x, summary_bb.Max.y + spacing, summary_bb.Max.x, bb.Max.y);
|
const ImRect unlock_bb(summary_bb.Min.x, summary_bb.Max.y + spacing, summary_bb.Max.x, bb.Max.y);
|
||||||
ImGui::RenderTextClipped(unlock_bb.Min, unlock_bb.Max, text, text.GetCharArray() + text.GetLength(), nullptr,
|
ImGui::RenderTextClipped(unlock_bb.Min, unlock_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
|
||||||
ImVec2(0.0f, 0.0f), &unlock_bb);
|
&unlock_bb);
|
||||||
}
|
}
|
||||||
else if (is_measured)
|
else if (is_measured)
|
||||||
{
|
{
|
||||||
|
@ -2399,43 +2397,43 @@ void Achievements::DrawLeaderboardsWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
||||||
text.Assign(Achievements::GetGameTitle());
|
text.assign(Achievements::GetGameTitle());
|
||||||
|
|
||||||
top += g_large_font->FontSize + spacing;
|
top += g_large_font->FontSize + spacing;
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.GetCharArray(), text.GetCharArray() + text.GetLength(),
|
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
|
||||||
nullptr, ImVec2(0.0f, 0.0f), &title_bb);
|
&title_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
if (is_leaderboard_open)
|
if (is_leaderboard_open)
|
||||||
{
|
{
|
||||||
const ImRect subtitle_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
const ImRect subtitle_bb(ImVec2(left, top), ImVec2(right, top + g_large_font->FontSize));
|
||||||
text.Assign(s_open_leaderboard->title);
|
text.assign(s_open_leaderboard->title);
|
||||||
|
|
||||||
top += g_large_font->FontSize + spacing_small;
|
top += g_large_font->FontSize + spacing_small;
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::RenderTextClipped(subtitle_bb.Min, subtitle_bb.Max, text.GetCharArray(),
|
ImGui::RenderTextClipped(subtitle_bb.Min, subtitle_bb.Max, text.c_str(), text.end_ptr(), nullptr,
|
||||||
text.GetCharArray() + text.GetLength(), nullptr, ImVec2(0.0f, 0.0f), &subtitle_bb);
|
ImVec2(0.0f, 0.0f), &subtitle_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
text.Assign(s_open_leaderboard->description);
|
text.assign(s_open_leaderboard->description);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
for (u32 i = 0; i < s_leaderboard_list->num_buckets; i++)
|
for (u32 i = 0; i < s_leaderboard_list->num_buckets; i++)
|
||||||
count += s_leaderboard_list->buckets[i].num_leaderboards;
|
count += s_leaderboard_list->buckets[i].num_leaderboards;
|
||||||
text.Fmt(TRANSLATE_FS("Achievements", "This game has {} leaderboards."), count);
|
text.fmt(TRANSLATE_FS("Achievements", "This game has {} leaderboards."), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + g_medium_font->FontSize));
|
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + g_medium_font->FontSize));
|
||||||
top += g_medium_font->FontSize + spacing_small;
|
top += g_medium_font->FontSize + spacing_small;
|
||||||
|
|
||||||
ImGui::PushFont(g_medium_font);
|
ImGui::PushFont(g_medium_font);
|
||||||
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.GetCharArray(),
|
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr,
|
||||||
text.GetCharArray() + text.GetLength(), nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
|
ImVec2(0.0f, 0.0f), &summary_bb);
|
||||||
|
|
||||||
if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive())
|
if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive())
|
||||||
{
|
{
|
||||||
|
@ -2646,7 +2644,7 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
|
||||||
float text_start_x = bb.Min.x + LayoutScale(15.0f);
|
float text_start_x = bb.Min.x + LayoutScale(15.0f);
|
||||||
SmallString text;
|
SmallString text;
|
||||||
|
|
||||||
text.Format("%u", entry.rank);
|
text.fmt("{}", entry.rank);
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
|
|
||||||
|
@ -2654,8 +2652,8 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 242, 0, 255));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 242, 0, 255));
|
||||||
|
|
||||||
const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
|
const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
|
||||||
ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, text.GetCharArray(), text.GetCharArray() + text.GetLength(),
|
ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
|
||||||
nullptr, ImVec2(0.0f, 0.0f), &rank_bb);
|
&rank_bb);
|
||||||
text_start_x += rank_column_width + column_spacing;
|
text_start_x += rank_column_width + column_spacing;
|
||||||
|
|
||||||
const float icon_size = bb.Max.y - bb.Min.y;
|
const float icon_size = bb.Max.y - bb.Min.y;
|
||||||
|
@ -2694,8 +2692,8 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
|
||||||
const ImRect time_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
|
const ImRect time_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
|
||||||
SmallString submit_time;
|
SmallString submit_time;
|
||||||
FullscreenUI::TimeToPrintableString(&submit_time, entry.submitted);
|
FullscreenUI::TimeToPrintableString(&submit_time, entry.submitted);
|
||||||
ImGui::RenderTextClipped(time_bb.Min, time_bb.Max, submit_time.GetCharArray(),
|
ImGui::RenderTextClipped(time_bb.Min, time_bb.Max, submit_time.c_str(), submit_time.end_ptr(), nullptr,
|
||||||
submit_time.GetCharArray() + submit_time.GetLength(), nullptr, ImVec2(0.0f, 0.0f), &time_bb);
|
ImVec2(0.0f, 0.0f), &time_bb);
|
||||||
|
|
||||||
if (is_self)
|
if (is_self)
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
@ -2716,7 +2714,7 @@ void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboar
|
||||||
static constexpr float alpha = 0.8f;
|
static constexpr float alpha = 0.8f;
|
||||||
|
|
||||||
TinyString id_str;
|
TinyString id_str;
|
||||||
id_str.Format("%u", lboard->id);
|
id_str.fmt("{}", lboard->id);
|
||||||
|
|
||||||
ImRect bb;
|
ImRect bb;
|
||||||
bool visible, hovered;
|
bool visible, hovered;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -182,7 +182,7 @@ void BIOS::PatchBIOS(u8* image, u32 image_size, u32 address, u32 value, u32 mask
|
||||||
CPU::DisassembleInstruction(&old_disasm, address, existing_value);
|
CPU::DisassembleInstruction(&old_disasm, address, existing_value);
|
||||||
CPU::DisassembleInstruction(&new_disasm, address, new_value);
|
CPU::DisassembleInstruction(&new_disasm, address, new_value);
|
||||||
Log_DevPrintf("BIOS-Patch 0x%08X (+0x%X): 0x%08X %s -> %08X %s", address, offset, existing_value,
|
Log_DevPrintf("BIOS-Patch 0x%08X (+0x%X): 0x%08X %s -> %08X %s", address, offset, existing_value,
|
||||||
old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray());
|
old_disasm.c_str(), new_value, new_disasm.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BIOS::PatchBIOSFastBoot(u8* image, u32 image_size)
|
bool BIOS::PatchBIOSFastBoot(u8* image, u32 image_size)
|
||||||
|
|
|
@ -770,22 +770,22 @@ static TickCount DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, P
|
||||||
u32& value)
|
u32& value)
|
||||||
{
|
{
|
||||||
SmallString str;
|
SmallString str;
|
||||||
str.AppendString("Invalid bus ");
|
str.append("Invalid bus ");
|
||||||
if (size == MemoryAccessSize::Byte)
|
if (size == MemoryAccessSize::Byte)
|
||||||
str.AppendString("byte");
|
str.append("byte");
|
||||||
if (size == MemoryAccessSize::HalfWord)
|
if (size == MemoryAccessSize::HalfWord)
|
||||||
str.AppendString("word");
|
str.append("word");
|
||||||
if (size == MemoryAccessSize::Word)
|
if (size == MemoryAccessSize::Word)
|
||||||
str.AppendString("dword");
|
str.append("dword");
|
||||||
str.AppendCharacter(' ');
|
str.append(' ');
|
||||||
if (type == MemoryAccessType::Read)
|
if (type == MemoryAccessType::Read)
|
||||||
str.AppendString("read");
|
str.append("read");
|
||||||
else
|
else
|
||||||
str.AppendString("write");
|
str.append("write");
|
||||||
|
|
||||||
str.AppendFormattedString(" at address 0x%08X", address);
|
str.append_fmt(" at address 0x{:08X}", address);
|
||||||
if (type == MemoryAccessType::Write)
|
if (type == MemoryAccessType::Write)
|
||||||
str.AppendFormattedString(" (value 0x%08X)", value);
|
str.append_fmt(" (value 0x{:08X})", value);
|
||||||
|
|
||||||
Log_ErrorPrint(str);
|
Log_ErrorPrint(str);
|
||||||
if (type == MemoryAccessType::Read)
|
if (type == MemoryAccessType::Read)
|
||||||
|
|
|
@ -803,7 +803,7 @@ bool CDROM::PrecacheMedia()
|
||||||
TinyString CDROM::LBAToMSFString(CDImage::LBA lba)
|
TinyString CDROM::LBAToMSFString(CDImage::LBA lba)
|
||||||
{
|
{
|
||||||
const auto pos = CDImage::Position::FromLBA(lba);
|
const auto pos = CDImage::Position::FromLBA(lba);
|
||||||
return TinyString::FromFmt("{:02d}:{:02d}:{:02d}", pos.minute, pos.second, pos.frame);
|
return TinyString::from_fmt("{:02d}:{:02d}:{:02d}", pos.minute, pos.second, pos.frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDROM::SetReadaheadSectors(u32 readahead_sectors)
|
void CDROM::SetReadaheadSectors(u32 readahead_sectors)
|
||||||
|
@ -2436,7 +2436,7 @@ void CDROM::UpdatePhysicalPosition(bool update_logical)
|
||||||
const CDImage::LBA new_physical_lba = base + new_offset;
|
const CDImage::LBA new_physical_lba = base + new_offset;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
Log_DevPrintf("Tick diff %u, sector diff %u, old pos %s, new pos %s", diff, sector_diff,
|
Log_DevPrintf("Tick diff %u, sector diff %u, old pos %s, new pos %s", diff, sector_diff,
|
||||||
LBAToMSFString(s_physical_lba).GetCharArray(), LBAToMSFString(new_physical_lba).GetCharArray());
|
LBAToMSFString(s_physical_lba).c_str(), LBAToMSFString(new_physical_lba).c_str());
|
||||||
#endif
|
#endif
|
||||||
if (s_physical_lba != new_physical_lba)
|
if (s_physical_lba != new_physical_lba)
|
||||||
{
|
{
|
||||||
|
@ -2575,7 +2575,7 @@ void CDROM::DoSeekComplete(TickCount ticks_late)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("%s seek to [%s] failed", logical ? "Logical" : "Physical",
|
Log_WarningPrintf("%s seek to [%s] failed", logical ? "Logical" : "Physical",
|
||||||
LBAToMSFString(m_reader.GetLastReadSector()).GetCharArray());
|
LBAToMSFString(m_reader.GetLastReadSector()).c_str());
|
||||||
s_secondary_status.ClearActiveBits();
|
s_secondary_status.ClearActiveBits();
|
||||||
SendAsyncErrorResponse(STAT_SEEK_ERROR, 0x04);
|
SendAsyncErrorResponse(STAT_SEEK_ERROR, 0x04);
|
||||||
s_last_sector_header_valid = false;
|
s_last_sector_header_valid = false;
|
||||||
|
@ -2733,8 +2733,7 @@ void CDROM::DoSectorRead()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log_DevPrintf("Sector %u [%s] has invalid subchannel Q", s_current_lba,
|
Log_DevPrintf("Sector %u [%s] has invalid subchannel Q", s_current_lba, LBAToMSFString(s_current_lba).c_str());
|
||||||
LBAToMSFString(s_current_lba).GetCharArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subq.track_number_bcd == CDImage::LEAD_OUT_TRACK_NUMBER)
|
if (subq.track_number_bcd == CDImage::LEAD_OUT_TRACK_NUMBER)
|
||||||
|
@ -2806,7 +2805,7 @@ void CDROM::ProcessDataSector(const u8* raw_sector, const CDImage::SubChannelQ&
|
||||||
{
|
{
|
||||||
const u32 sb_num = (s_current_write_sector_buffer + 1) % NUM_SECTOR_BUFFERS;
|
const u32 sb_num = (s_current_write_sector_buffer + 1) % NUM_SECTOR_BUFFERS;
|
||||||
Log_DevPrintf("Read sector %u [%s]: mode %u submode 0x%02X into buffer %u", s_current_lba,
|
Log_DevPrintf("Read sector %u [%s]: mode %u submode 0x%02X into buffer %u", s_current_lba,
|
||||||
LBAToMSFString(s_current_lba).GetCharArray(), ZeroExtend32(s_last_sector_header.sector_mode),
|
LBAToMSFString(s_current_lba).c_str(), ZeroExtend32(s_last_sector_header.sector_mode),
|
||||||
ZeroExtend32(s_last_sector_subheader.submode.bits), sb_num);
|
ZeroExtend32(s_last_sector_subheader.submode.bits), sb_num);
|
||||||
|
|
||||||
if (s_mode.xa_enable && s_last_sector_header.sector_mode == 2)
|
if (s_mode.xa_enable && s_last_sector_header.sector_mode == 2)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "common/byte_stream.h"
|
#include "common/byte_stream.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "cpu_code_cache.h"
|
#include "cpu_code_cache.h"
|
||||||
|
@ -397,9 +397,9 @@ bool CheatList::LoadFromLibretroString(const std::string& str)
|
||||||
|
|
||||||
for (u32 i = 0; i < num_cheats; i++)
|
for (u32 i = 0; i < num_cheats; i++)
|
||||||
{
|
{
|
||||||
const std::string* desc = FindKey(kvp, TinyString::FromFormat("cheat%u_desc", i));
|
const std::string* desc = FindKey(kvp, TinyString::from_fmt("cheat{}_desc", i));
|
||||||
const std::string* code = FindKey(kvp, TinyString::FromFormat("cheat%u_code", i));
|
const std::string* code = FindKey(kvp, TinyString::from_fmt("cheat{}_code", i));
|
||||||
const std::string* enable = FindKey(kvp, TinyString::FromFormat("cheat%u_enable", i));
|
const std::string* enable = FindKey(kvp, TinyString::from_fmt("cheat{}_enable", i));
|
||||||
if (!desc || !code || !enable)
|
if (!desc || !code || !enable)
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Missing desc/code/enable for cheat %u", i);
|
Log_WarningPrintf("Missing desc/code/enable for cheat %u", i);
|
||||||
|
|
|
@ -799,7 +799,7 @@ bool CompileBlock(CodeBlock* block, bool allow_flush)
|
||||||
{
|
{
|
||||||
CPU::DisassembleInstruction(&disasm, cbi.pc, cbi.instruction.bits);
|
CPU::DisassembleInstruction(&disasm, cbi.pc, cbi.instruction.bits);
|
||||||
Log_DebugPrintf("[%s %s 0x%08X] %08X %s", cbi.is_branch_delay_slot ? "BD" : " ",
|
Log_DebugPrintf("[%s %s 0x%08X] %08X %s", cbi.is_branch_delay_slot ? "BD" : " ",
|
||||||
cbi.is_load_delay_slot ? "LD" : " ", cbi.pc, cbi.instruction.bits, disasm.GetCharArray());
|
cbi.is_load_delay_slot ? "LD" : " ", cbi.pc, cbi.instruction.bits, disasm.c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -571,15 +571,15 @@ static void TracePrintInstruction()
|
||||||
TinyString comment;
|
TinyString comment;
|
||||||
DisassembleInstruction(&instr, pc, bits);
|
DisassembleInstruction(&instr, pc, bits);
|
||||||
DisassembleInstructionComment(&comment, pc, bits, &g_state.regs);
|
DisassembleInstructionComment(&comment, pc, bits, &g_state.regs);
|
||||||
if (!comment.IsEmpty())
|
if (!comment.empty())
|
||||||
{
|
{
|
||||||
for (u32 i = instr.GetLength(); i < 30; i++)
|
for (u32 i = instr.length(); i < 30; i++)
|
||||||
instr.AppendCharacter(' ');
|
instr.append(' ');
|
||||||
instr.AppendString("; ");
|
instr.append("; ");
|
||||||
instr.AppendString(comment);
|
instr.append(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::printf("%08x: %08x %s\n", pc, bits, instr.GetCharArray());
|
std::printf("%08x: %08x %s\n", pc, bits, instr.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -590,15 +590,15 @@ static void PrintInstruction(u32 bits, u32 pc, Registers* regs, const char* pref
|
||||||
TinyString comment;
|
TinyString comment;
|
||||||
DisassembleInstruction(&instr, pc, bits);
|
DisassembleInstruction(&instr, pc, bits);
|
||||||
DisassembleInstructionComment(&comment, pc, bits, regs);
|
DisassembleInstructionComment(&comment, pc, bits, regs);
|
||||||
if (!comment.IsEmpty())
|
if (!comment.empty())
|
||||||
{
|
{
|
||||||
for (u32 i = instr.GetLength(); i < 30; i++)
|
for (u32 i = instr.length(); i < 30; i++)
|
||||||
instr.AppendCharacter(' ');
|
instr.append(' ');
|
||||||
instr.AppendString("; ");
|
instr.append("; ");
|
||||||
instr.AppendString(comment);
|
instr.append(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_DevPrintf("%s%08x: %08x %s", prefix, pc, bits, instr.GetCharArray());
|
Log_DevPrintf("%s%08x: %08x %s", prefix, pc, bits, instr.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LogInstruction(u32 bits, u32 pc, Registers* regs)
|
static void LogInstruction(u32 bits, u32 pc, Registers* regs)
|
||||||
|
@ -607,15 +607,15 @@ static void LogInstruction(u32 bits, u32 pc, Registers* regs)
|
||||||
TinyString comment;
|
TinyString comment;
|
||||||
DisassembleInstruction(&instr, pc, bits);
|
DisassembleInstruction(&instr, pc, bits);
|
||||||
DisassembleInstructionComment(&comment, pc, bits, regs);
|
DisassembleInstructionComment(&comment, pc, bits, regs);
|
||||||
if (!comment.IsEmpty())
|
if (!comment.empty())
|
||||||
{
|
{
|
||||||
for (u32 i = instr.GetLength(); i < 30; i++)
|
for (u32 i = instr.length(); i < 30; i++)
|
||||||
instr.AppendCharacter(' ');
|
instr.append(' ');
|
||||||
instr.AppendString("; ");
|
instr.append("; ");
|
||||||
instr.AppendString(comment);
|
instr.append(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteToExecutionLog("%08x: %08x %s\n", pc, bits, instr.GetCharArray());
|
WriteToExecutionLog("%08x: %08x %s\n", pc, bits, instr.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HandleWriteSyscall()
|
static void HandleWriteSyscall()
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#include "cpu_disasm.h"
|
#include "cpu_disasm.h"
|
||||||
#include "common/assert.h"
|
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
|
@ -169,9 +172,9 @@ static const std::array<std::pair<CopCommonInstruction, const char*>, 4> s_cop_c
|
||||||
|
|
||||||
static const std::array<std::pair<Cop0Instruction, const char*>, 1> s_cop0_table = {{{Cop0Instruction::rfe, "rfe"}}};
|
static const std::array<std::pair<Cop0Instruction, const char*>, 1> s_cop0_table = {{{Cop0Instruction::rfe, "rfe"}}};
|
||||||
|
|
||||||
static void FormatInstruction(String* dest, const Instruction inst, u32 pc, const char* format)
|
static void FormatInstruction(SmallStringBase* dest, const Instruction inst, u32 pc, const char* format)
|
||||||
{
|
{
|
||||||
dest->Clear();
|
dest->clear();
|
||||||
|
|
||||||
const char* str = format;
|
const char* str = format;
|
||||||
while (*str != '\0')
|
while (*str != '\0')
|
||||||
|
@ -179,77 +182,77 @@ static void FormatInstruction(String* dest, const Instruction inst, u32 pc, cons
|
||||||
const char ch = *(str++);
|
const char ch = *(str++);
|
||||||
if (ch != '$')
|
if (ch != '$')
|
||||||
{
|
{
|
||||||
dest->AppendCharacter(ch);
|
dest->append(ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::strncmp(str, "rs", 2) == 0)
|
if (std::strncmp(str, "rs", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendString(GetRegName(inst.r.rs));
|
dest->append(GetRegName(inst.r.rs));
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "rt", 2) == 0)
|
else if (std::strncmp(str, "rt", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendString(GetRegName(inst.r.rt));
|
dest->append(GetRegName(inst.r.rt));
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "rd", 2) == 0)
|
else if (std::strncmp(str, "rd", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendString(GetRegName(inst.r.rd));
|
dest->append(GetRegName(inst.r.rd));
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "shamt", 5) == 0)
|
else if (std::strncmp(str, "shamt", 5) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%d", ZeroExtend32(inst.r.shamt.GetValue()));
|
dest->append_fmt("{}", ZeroExtend32(inst.r.shamt.GetValue()));
|
||||||
str += 5;
|
str += 5;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "immu", 4) == 0)
|
else if (std::strncmp(str, "immu", 4) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%u", inst.i.imm_zext32());
|
dest->append_fmt("{}", inst.i.imm_zext32());
|
||||||
str += 4;
|
str += 4;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "imm", 3) == 0)
|
else if (std::strncmp(str, "imm", 3) == 0)
|
||||||
{
|
{
|
||||||
// dest->AppendFormattedString("%d", static_cast<int>(inst.i.imm_sext32()));
|
// dest->AppendFormattedString("%d", static_cast<int>(inst.i.imm_sext32()));
|
||||||
dest->AppendFormattedString("%04x", inst.i.imm_zext32());
|
dest->append_fmt("{:04x}", inst.i.imm_zext32());
|
||||||
str += 3;
|
str += 3;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "rel", 3) == 0)
|
else if (std::strncmp(str, "rel", 3) == 0)
|
||||||
{
|
{
|
||||||
const u32 target = (pc + UINT32_C(4)) + (inst.i.imm_sext32() << 2);
|
const u32 target = (pc + UINT32_C(4)) + (inst.i.imm_sext32() << 2);
|
||||||
dest->AppendFormattedString("%08x", target);
|
dest->append_fmt("{:08x}", target);
|
||||||
str += 3;
|
str += 3;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "offsetrs", 8) == 0)
|
else if (std::strncmp(str, "offsetrs", 8) == 0)
|
||||||
{
|
{
|
||||||
const s32 offset = static_cast<s32>(inst.i.imm_sext32());
|
const s32 offset = static_cast<s32>(inst.i.imm_sext32());
|
||||||
dest->AppendFormattedString("%d(%s)", offset, GetRegName(inst.i.rs));
|
dest->append_fmt("{}({})", offset, GetRegName(inst.i.rs));
|
||||||
str += 8;
|
str += 8;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "jt", 2) == 0)
|
else if (std::strncmp(str, "jt", 2) == 0)
|
||||||
{
|
{
|
||||||
const u32 target = ((pc + UINT32_C(4)) & UINT32_C(0xF0000000)) | (inst.j.target << 2);
|
const u32 target = ((pc + UINT32_C(4)) & UINT32_C(0xF0000000)) | (inst.j.target << 2);
|
||||||
dest->AppendFormattedString("%08x", target);
|
dest->append_fmt("{:08x}", target);
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "copcc", 5) == 0)
|
else if (std::strncmp(str, "copcc", 5) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendCharacter(((inst.bits & (UINT32_C(1) << 24)) != 0) ? 't' : 'f');
|
dest->append(((inst.bits & (UINT32_C(1) << 24)) != 0) ? 't' : 'f');
|
||||||
str += 5;
|
str += 5;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "coprd", 5) == 0)
|
else if (std::strncmp(str, "coprd", 5) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%u", ZeroExtend32(static_cast<u8>(inst.r.rd.GetValue())));
|
dest->append_fmt("{}", ZeroExtend32(static_cast<u8>(inst.r.rd.GetValue())));
|
||||||
str += 5;
|
str += 5;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "coprt", 5) == 0)
|
else if (std::strncmp(str, "coprt", 5) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%u", ZeroExtend32(static_cast<u8>(inst.r.rt.GetValue())));
|
dest->append_fmt("{}", ZeroExtend32(static_cast<u8>(inst.r.rt.GetValue())));
|
||||||
str += 5;
|
str += 5;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "cop", 3) == 0)
|
else if (std::strncmp(str, "cop", 3) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%u", static_cast<u8>(inst.op.GetValue()) & INSTRUCTION_COP_N_MASK);
|
dest->append_fmt("{}", static_cast<u8>(inst.op.GetValue()) & INSTRUCTION_COP_N_MASK);
|
||||||
str += 3;
|
str += 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -259,7 +262,7 @@ static void FormatInstruction(String* dest, const Instruction inst, u32 pc, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FormatComment(String* dest, const Instruction inst, u32 pc, Registers* regs, const char* format)
|
static void FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, Registers* regs, const char* format)
|
||||||
{
|
{
|
||||||
const char* str = format;
|
const char* str = format;
|
||||||
while (*str != '\0')
|
while (*str != '\0')
|
||||||
|
@ -270,21 +273,21 @@ static void FormatComment(String* dest, const Instruction inst, u32 pc, Register
|
||||||
|
|
||||||
if (std::strncmp(str, "rs", 2) == 0)
|
if (std::strncmp(str, "rs", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%s%s=0x%08X", dest->IsEmpty() ? "" : ", ", GetRegName(inst.r.rs),
|
dest->append_fmt("{}{}=0x{:08X}", dest->empty() ? "" : ", ", GetRegName(inst.r.rs),
|
||||||
regs->r[static_cast<u8>(inst.r.rs.GetValue())]);
|
regs->r[static_cast<u8>(inst.r.rs.GetValue())]);
|
||||||
|
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "rt", 2) == 0)
|
else if (std::strncmp(str, "rt", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%s%s=0x%08X", dest->IsEmpty() ? "" : ", ", GetRegName(inst.r.rt),
|
dest->append_fmt("{}{}=0x{:08X}", dest->empty() ? "" : ", ", GetRegName(inst.r.rt),
|
||||||
regs->r[static_cast<u8>(inst.r.rt.GetValue())]);
|
regs->r[static_cast<u8>(inst.r.rt.GetValue())]);
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "rd", 2) == 0)
|
else if (std::strncmp(str, "rd", 2) == 0)
|
||||||
{
|
{
|
||||||
dest->AppendFormattedString("%s%s=0x%08X", dest->IsEmpty() ? "" : ", ", GetRegName(inst.r.rd),
|
dest->append_fmt("{}{}=0x{:08X}", dest->empty() ? "" : ", ", GetRegName(inst.r.rd),
|
||||||
regs->r[static_cast<u8>(inst.r.rd.GetValue())]);
|
regs->r[static_cast<u8>(inst.r.rd.GetValue())]);
|
||||||
str += 2;
|
str += 2;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "shamt", 5) == 0)
|
else if (std::strncmp(str, "shamt", 5) == 0)
|
||||||
|
@ -306,8 +309,8 @@ static void FormatComment(String* dest, const Instruction inst, u32 pc, Register
|
||||||
else if (std::strncmp(str, "offsetrs", 8) == 0)
|
else if (std::strncmp(str, "offsetrs", 8) == 0)
|
||||||
{
|
{
|
||||||
const s32 offset = static_cast<s32>(inst.i.imm_sext32());
|
const s32 offset = static_cast<s32>(inst.i.imm_sext32());
|
||||||
dest->AppendFormattedString("%saddr=0x%08X", dest->IsEmpty() ? "" : ", ",
|
dest->append_fmt("{}addr={:08X}", dest->empty() ? "" : ", ",
|
||||||
regs->r[static_cast<u8>(inst.i.rs.GetValue())] + offset);
|
regs->r[static_cast<u8>(inst.i.rs.GetValue())] + offset);
|
||||||
str += 8;
|
str += 8;
|
||||||
}
|
}
|
||||||
else if (std::strncmp(str, "jt", 2) == 0)
|
else if (std::strncmp(str, "jt", 2) == 0)
|
||||||
|
@ -338,8 +341,8 @@ static void FormatComment(String* dest, const Instruction inst, u32 pc, Register
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void FormatCopInstruction(String* dest, u32 pc, const Instruction inst, const std::pair<T, const char*>* table,
|
static void FormatCopInstruction(SmallStringBase* dest, u32 pc, const Instruction inst,
|
||||||
size_t table_size, T table_key)
|
const std::pair<T, const char*>* table, size_t table_size, T table_key)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < table_size; i++)
|
for (size_t i = 0; i < table_size; i++)
|
||||||
{
|
{
|
||||||
|
@ -350,12 +353,12 @@ void FormatCopInstruction(String* dest, u32 pc, const Instruction inst, const st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
dest->fmt("<cop{} 0x{:08X}>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void FormatCopComment(String* dest, u32 pc, Registers* regs, const Instruction inst,
|
static void FormatCopComment(SmallStringBase* dest, u32 pc, Registers* regs, const Instruction inst,
|
||||||
const std::pair<T, const char*>* table, size_t table_size, T table_key)
|
const std::pair<T, const char*>* table, size_t table_size, T table_key)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < table_size; i++)
|
for (size_t i = 0; i < table_size; i++)
|
||||||
{
|
{
|
||||||
|
@ -367,7 +370,7 @@ void FormatCopComment(String* dest, u32 pc, Registers* regs, const Instruction i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassembleInstruction(String* dest, u32 pc, u32 bits)
|
void DisassembleInstruction(SmallStringBase* dest, u32 pc, u32 bits)
|
||||||
{
|
{
|
||||||
const Instruction inst{bits};
|
const Instruction inst{bits};
|
||||||
switch (inst.op)
|
switch (inst.op)
|
||||||
|
@ -400,7 +403,7 @@ void DisassembleInstruction(String* dest, u32 pc, u32 bits)
|
||||||
case InstructionOp::cop3:
|
case InstructionOp::cop3:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
dest->fmt("<cop{} 0x{:08X}>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -427,7 +430,7 @@ void DisassembleInstruction(String* dest, u32 pc, u32 bits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassembleInstructionComment(String* dest, u32 pc, u32 bits, Registers* regs)
|
void DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, Registers* regs)
|
||||||
{
|
{
|
||||||
const Instruction inst{bits};
|
const Instruction inst{bits};
|
||||||
switch (inst.op)
|
switch (inst.op)
|
||||||
|
@ -461,7 +464,7 @@ void DisassembleInstructionComment(String* dest, u32 pc, u32 bits, Registers* re
|
||||||
case InstructionOp::cop3:
|
case InstructionOp::cop3:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
dest->fmt("<cop{} 0x{:08X}>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/string.h"
|
|
||||||
#include "cpu_types.h"
|
#include "cpu_types.h"
|
||||||
|
|
||||||
|
class SmallStringBase;
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
void DisassembleInstruction(String* dest, u32 pc, u32 bits);
|
void DisassembleInstruction(SmallStringBase* dest, u32 pc, u32 bits);
|
||||||
void DisassembleInstructionComment(String* dest, u32 pc, u32 bits, Registers* regs);
|
void DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, Registers* regs);
|
||||||
} // namespace CPU
|
} // namespace CPU
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/make_array.h"
|
#include "common/make_array.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/threading.h"
|
#include "common/threading.h"
|
||||||
|
|
||||||
|
@ -54,19 +54,23 @@ Log_SetChannel(FullscreenUI);
|
||||||
|
|
||||||
#define TR_CONTEXT "FullscreenUI"
|
#define TR_CONTEXT "FullscreenUI"
|
||||||
|
|
||||||
namespace FullscreenUI {
|
namespace {
|
||||||
template<size_t L>
|
template<size_t L>
|
||||||
class IconStackString : public StackString<L>
|
class IconStackString : public SmallStackString<L>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ALWAYS_INLINE IconStackString(const char* icon, const char* str)
|
ALWAYS_INLINE IconStackString(const char* icon, const char* str)
|
||||||
{
|
{
|
||||||
StackString<L>::Fmt("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str));
|
SmallStackString<L>::fmt("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str));
|
||||||
|
}
|
||||||
|
ALWAYS_INLINE IconStackString(const char* icon, const char* str, const char* suffix)
|
||||||
|
{
|
||||||
|
SmallStackString<L>::fmt("{} {}##{}", icon, Host::TranslateToStringView(TR_CONTEXT, str), suffix);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace FullscreenUI
|
} // namespace
|
||||||
|
|
||||||
#define FSUI_ICONSTR(icon, str) FullscreenUI::IconStackString<128>(icon, str).GetCharArray()
|
#define FSUI_ICONSTR(icon, str) IconStackString<128>(icon, str).c_str()
|
||||||
#define FSUI_STR(str) Host::TranslateToString(TR_CONTEXT, str)
|
#define FSUI_STR(str) Host::TranslateToString(TR_CONTEXT, str)
|
||||||
#define FSUI_CSTR(str) Host::TranslateToCString(TR_CONTEXT, str)
|
#define FSUI_CSTR(str) Host::TranslateToCString(TR_CONTEXT, str)
|
||||||
#define FSUI_VSTR(str) Host::TranslateToStringView(TR_CONTEXT, str)
|
#define FSUI_VSTR(str) Host::TranslateToStringView(TR_CONTEXT, str)
|
||||||
|
@ -472,7 +476,7 @@ static GameListPage s_game_list_page = GameListPage::Grid;
|
||||||
// Utility
|
// Utility
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FullscreenUI::TimeToPrintableString(String* str, time_t t)
|
void FullscreenUI::TimeToPrintableString(SmallStringBase* str, time_t t)
|
||||||
{
|
{
|
||||||
struct tm lt = {};
|
struct tm lt = {};
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -483,7 +487,7 @@ void FullscreenUI::TimeToPrintableString(String* str, time_t t)
|
||||||
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
std::strftime(buf, sizeof(buf), "%c", <);
|
std::strftime(buf, sizeof(buf), "%c", <);
|
||||||
str->Assign(buf);
|
str->assign(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullscreenUI::StartAsyncOp(std::function<void(::ProgressCallback*)> callback, std::string name)
|
void FullscreenUI::StartAsyncOp(std::function<void(::ProgressCallback*)> callback, std::string name)
|
||||||
|
@ -1342,7 +1346,7 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
||||||
const char* name, const char* display_name, bool show_type)
|
const char* name, const char* display_name, bool show_type)
|
||||||
{
|
{
|
||||||
TinyString title;
|
TinyString title;
|
||||||
title.Fmt("{}/{}", section, name);
|
title.fmt("{}/{}", section, name);
|
||||||
|
|
||||||
ImRect bb;
|
ImRect bb;
|
||||||
bool visible, hovered, clicked;
|
bool visible, hovered, clicked;
|
||||||
|
@ -1360,17 +1364,17 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case InputBindingInfo::Type::Button:
|
case InputBindingInfo::Type::Button:
|
||||||
title = fmt::format(ICON_FA_DOT_CIRCLE "{}", display_name);
|
title.fmt(ICON_FA_DOT_CIRCLE "{}", display_name);
|
||||||
break;
|
break;
|
||||||
case InputBindingInfo::Type::Axis:
|
case InputBindingInfo::Type::Axis:
|
||||||
case InputBindingInfo::Type::HalfAxis:
|
case InputBindingInfo::Type::HalfAxis:
|
||||||
title = fmt::format(ICON_FA_BULLSEYE "{}", display_name);
|
title.fmt(ICON_FA_BULLSEYE "{}", display_name);
|
||||||
break;
|
break;
|
||||||
case InputBindingInfo::Type::Motor:
|
case InputBindingInfo::Type::Motor:
|
||||||
title = fmt::format(ICON_FA_BELL "{}", display_name);
|
title.fmt(ICON_FA_BELL "{}", display_name);
|
||||||
break;
|
break;
|
||||||
case InputBindingInfo::Type::Macro:
|
case InputBindingInfo::Type::Macro:
|
||||||
title = fmt::format(ICON_FA_PIZZA_SLICE "{}", display_name);
|
title.fmt(ICON_FA_PIZZA_SLICE "{}", display_name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
title = display_name;
|
title = display_name;
|
||||||
|
@ -1379,8 +1383,8 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, show_type ? title.GetCharArray() : display_name, nullptr,
|
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, show_type ? title.c_str() : display_name, nullptr, nullptr,
|
||||||
nullptr, ImVec2(0.0f, 0.0f), &title_bb);
|
ImVec2(0.0f, 0.0f), &title_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
const std::string value(bsi->GetStringValue(section, name));
|
const std::string value(bsi->GetStringValue(section, name));
|
||||||
|
@ -1521,12 +1525,12 @@ void FullscreenUI::DrawInputBindingWindow()
|
||||||
if (ImGui::BeginPopupModal(title, nullptr,
|
if (ImGui::BeginPopupModal(title, nullptr,
|
||||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoInputs))
|
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoInputs))
|
||||||
{
|
{
|
||||||
ImGui::TextWrapped("%s", SmallString::FromFmt(FSUI_FSTR("Setting {} binding {}."), s_input_binding_section,
|
ImGui::TextWrapped("%s", SmallString::from_fmt(FSUI_FSTR("Setting {} binding {}."), s_input_binding_section,
|
||||||
s_input_binding_display_name)
|
s_input_binding_display_name)
|
||||||
.GetCharArray());
|
.c_str());
|
||||||
ImGui::TextUnformatted(FSUI_CSTR("Push a controller button or axis now."));
|
ImGui::TextUnformatted(FSUI_CSTR("Push a controller button or axis now."));
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
ImGui::TextUnformatted(SmallString::FromFmt(FSUI_FSTR("Timing out in {:.0f} seconds..."), time_remaining));
|
ImGui::TextUnformatted(SmallString::from_fmt(FSUI_FSTR("Timing out in {:.0f} seconds..."), time_remaining));
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2004,7 +2008,7 @@ void FullscreenUI::DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* tit
|
||||||
bsi->GetOptionalIntValue(section, key, game_settings ? std::nullopt : std::optional<int>(default_value));
|
bsi->GetOptionalIntValue(section, key, game_settings ? std::nullopt : std::optional<int>(default_value));
|
||||||
TinyString value_text;
|
TinyString value_text;
|
||||||
if (value.has_value())
|
if (value.has_value())
|
||||||
value_text.Format(format, value.value());
|
value_text.format(format, value.value());
|
||||||
else
|
else
|
||||||
value_text = FSUI_VSTR("Use Global Setting");
|
value_text = FSUI_VSTR("Use Global Setting");
|
||||||
|
|
||||||
|
@ -2821,14 +2825,14 @@ void FullscreenUI::DrawBIOSSettingsPage()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TinyString title;
|
TinyString title;
|
||||||
title.Fmt(FSUI_FSTR("BIOS for {}"), Settings::GetConsoleRegionDisplayName(region));
|
title.fmt(FSUI_FSTR("BIOS for {}"), Settings::GetConsoleRegionDisplayName(region));
|
||||||
|
|
||||||
const std::optional<std::string> filename(bsi->GetOptionalStringValue(
|
const std::optional<std::string> filename(bsi->GetOptionalStringValue(
|
||||||
"BIOS", config_keys[i], game_settings ? std::nullopt : std::optional<const char*>("")));
|
"BIOS", config_keys[i], game_settings ? std::nullopt : std::optional<const char*>("")));
|
||||||
|
|
||||||
if (MenuButtonWithValue(title,
|
if (MenuButtonWithValue(title,
|
||||||
SmallString::FromFmt(FSUI_FSTR("BIOS to use when emulating {} consoles."),
|
SmallString::from_fmt(FSUI_FSTR("BIOS to use when emulating {} consoles."),
|
||||||
Settings::GetConsoleRegionDisplayName(region)),
|
Settings::GetConsoleRegionDisplayName(region)),
|
||||||
filename.has_value() ? (filename->empty() ? FSUI_CSTR("Auto-Detect") : filename->c_str()) :
|
filename.has_value() ? (filename->empty() ? FSUI_CSTR("Auto-Detect") : filename->c_str()) :
|
||||||
FSUI_CSTR("Use Global Setting")))
|
FSUI_CSTR("Use Global Setting")))
|
||||||
{
|
{
|
||||||
|
@ -3052,7 +3056,7 @@ void FullscreenUI::DrawEmulationSettingsPage()
|
||||||
|
|
||||||
u64 ram_usage, vram_usage;
|
u64 ram_usage, vram_usage;
|
||||||
System::CalculateRewindMemoryUsage(rewind_save_slots, &ram_usage, &vram_usage);
|
System::CalculateRewindMemoryUsage(rewind_save_slots, &ram_usage, &vram_usage);
|
||||||
rewind_summary.Fmt(
|
rewind_summary.fmt(
|
||||||
FSUI_FSTR("Rewind for {0} frames, lasting {1:.2f} seconds will require up to {3} MB of RAM and {4} MB of VRAM."),
|
FSUI_FSTR("Rewind for {0} frames, lasting {1:.2f} seconds will require up to {3} MB of RAM and {4} MB of VRAM."),
|
||||||
rewind_save_slots, duration, ram_usage / 1048576, vram_usage / 1048576);
|
rewind_save_slots, duration, ram_usage / 1048576, vram_usage / 1048576);
|
||||||
}
|
}
|
||||||
|
@ -3277,18 +3281,18 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
|
|
||||||
if (mtap_enabled[mtap_port])
|
if (mtap_enabled[mtap_port])
|
||||||
{
|
{
|
||||||
MenuHeading(TinyString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}{}")), mtap_port + 1,
|
MenuHeading(TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}{}")), mtap_port + 1,
|
||||||
mtap_slot_names[mtap_slot]));
|
mtap_slot_names[mtap_slot]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MenuHeading(TinyString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), mtap_port + 1));
|
MenuHeading(TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_PLUG, "Controller Port {}")), mtap_port + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string section(fmt::format("Pad{}", global_slot + 1));
|
const std::string section(fmt::format("Pad{}", global_slot + 1));
|
||||||
const std::string type(bsi->GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(global_slot)));
|
const std::string type(bsi->GetStringValue(section.c_str(), "Type", Controller::GetDefaultPadType(global_slot)));
|
||||||
const Controller::ControllerInfo* ci = Controller::GetControllerInfo(type);
|
const Controller::ControllerInfo* ci = Controller::GetControllerInfo(type);
|
||||||
if (MenuButton(TinyString::FromFmt("{}##type{}", FSUI_ICONSTR(ICON_FA_GAMEPAD, "Controller Type"), global_slot),
|
if (MenuButton(TinyString::from_fmt("{}##type{}", FSUI_ICONSTR(ICON_FA_GAMEPAD, "Controller Type"), global_slot),
|
||||||
ci ? ci->display_name : FSUI_CSTR("Unknown")))
|
ci ? ci->display_name : FSUI_CSTR("Unknown")))
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::string, std::string>> raw_options(Controller::GetControllerTypeNames());
|
std::vector<std::pair<std::string, std::string>> raw_options(Controller::GetControllerTypeNames());
|
||||||
|
@ -3298,7 +3302,7 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
{
|
{
|
||||||
options.emplace_back(std::move(it.second), type == it.first);
|
options.emplace_back(std::move(it.second), type == it.first);
|
||||||
}
|
}
|
||||||
OpenChoiceDialog(TinyString::FromFmt(FSUI_FSTR("Port {} Controller Type"), global_slot + 1), false,
|
OpenChoiceDialog(TinyString::from_fmt(FSUI_FSTR("Port {} Controller Type"), global_slot + 1), false,
|
||||||
std::move(options),
|
std::move(options),
|
||||||
[game_settings, section,
|
[game_settings, section,
|
||||||
raw_options = std::move(raw_options)](s32 index, const std::string& title, bool checked) {
|
raw_options = std::move(raw_options)](s32 index, const std::string& title, bool checked) {
|
||||||
|
@ -3327,25 +3331,25 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
|
|
||||||
if (mtap_enabled[mtap_port])
|
if (mtap_enabled[mtap_port])
|
||||||
{
|
{
|
||||||
MenuHeading(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {}{} Macros")),
|
MenuHeading(SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {}{} Macros")),
|
||||||
mtap_port + 1, mtap_slot_names[mtap_slot]));
|
mtap_port + 1, mtap_slot_names[mtap_slot]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MenuHeading(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {} Macros")),
|
MenuHeading(SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_MICROCHIP, "Controller Port {} Macros")),
|
||||||
mtap_port + 1));
|
mtap_port + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++)
|
for (u32 macro_index = 0; macro_index < InputManager::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++)
|
||||||
{
|
{
|
||||||
DrawInputBindingButton(bsi, InputBindingInfo::Type::Macro, section.c_str(),
|
DrawInputBindingButton(bsi, InputBindingInfo::Type::Macro, section.c_str(),
|
||||||
TinyString::FromFmt("Macro{}", macro_index + 1),
|
TinyString::from_fmt("Macro{}", macro_index + 1),
|
||||||
TinyString::FromFmt(FSUI_FSTR("Macro {} Trigger"), macro_index + 1));
|
TinyString::from_fmt(FSUI_FSTR("Macro {} Trigger"), macro_index + 1));
|
||||||
|
|
||||||
std::string binds_string(
|
std::string binds_string(
|
||||||
bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str()));
|
bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str()));
|
||||||
if (MenuButton(
|
if (MenuButton(
|
||||||
TinyString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Macro {} Buttons")), macro_index + 1),
|
TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Macro {} Buttons")), macro_index + 1),
|
||||||
binds_string.empty() ? FSUI_CSTR("No Buttons Selected") : binds_string.c_str()))
|
binds_string.empty() ? FSUI_CSTR("No Buttons Selected") : binds_string.c_str()))
|
||||||
{
|
{
|
||||||
std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true));
|
std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true));
|
||||||
|
@ -3363,7 +3367,7 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenChoiceDialog(
|
OpenChoiceDialog(
|
||||||
TinyString::FromFmt(FSUI_FSTR("Select Macro {} Binds"), macro_index + 1), true, std::move(options),
|
TinyString::from_fmt(FSUI_FSTR("Select Macro {} Binds"), macro_index + 1), true, std::move(options),
|
||||||
[game_settings, section, macro_index, ci](s32 index, const std::string& title, bool checked) {
|
[game_settings, section, macro_index, ci](s32 index, const std::string& title, bool checked) {
|
||||||
// convert display name back to bind name
|
// convert display name back to bind name
|
||||||
std::string_view to_modify;
|
std::string_view to_modify;
|
||||||
|
@ -3409,13 +3413,13 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
|
|
||||||
const std::string freq_key(fmt::format("Macro{}Frequency", macro_index + 1));
|
const std::string freq_key(fmt::format("Macro{}Frequency", macro_index + 1));
|
||||||
const SmallString freq_title =
|
const SmallString freq_title =
|
||||||
SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Macro {} Frequency")), macro_index + 1);
|
SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Macro {} Frequency")), macro_index + 1);
|
||||||
s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0);
|
s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0);
|
||||||
SmallString freq_summary;
|
SmallString freq_summary;
|
||||||
if (frequency == 0)
|
if (frequency == 0)
|
||||||
freq_summary = FSUI_VSTR("Macro will not auto-toggle.");
|
freq_summary = FSUI_VSTR("Macro will not auto-toggle.");
|
||||||
else
|
else
|
||||||
freq_summary.Fmt(FSUI_FSTR("Macro will toggle every {} frames."), frequency);
|
freq_summary.fmt(FSUI_FSTR("Macro will toggle every {} frames."), frequency);
|
||||||
if (MenuButton(freq_title, freq_summary))
|
if (MenuButton(freq_title, freq_summary))
|
||||||
ImGui::OpenPopup(freq_title);
|
ImGui::OpenPopup(freq_title);
|
||||||
|
|
||||||
|
@ -3456,19 +3460,20 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||||
{
|
{
|
||||||
if (mtap_enabled[mtap_port])
|
if (mtap_enabled[mtap_port])
|
||||||
{
|
{
|
||||||
MenuHeading(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {}{} Settings")),
|
MenuHeading(
|
||||||
mtap_port + 1, mtap_slot_names[mtap_slot]));
|
SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {}{} Settings")),
|
||||||
|
mtap_port + 1, mtap_slot_names[mtap_slot]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MenuHeading(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")),
|
MenuHeading(SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SLIDERS_H, "Controller Port {} Settings")),
|
||||||
mtap_port + 1));
|
mtap_port + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const SettingInfo& si : ci->settings)
|
for (const SettingInfo& si : ci->settings)
|
||||||
{
|
{
|
||||||
TinyString title;
|
TinyString title;
|
||||||
title.Fmt(ICON_FA_COG "{}", si.display_name);
|
title.fmt(ICON_FA_COG "{}", si.display_name);
|
||||||
switch (si.type)
|
switch (si.type)
|
||||||
{
|
{
|
||||||
case SettingInfo::Type::Boolean:
|
case SettingInfo::Type::Boolean:
|
||||||
|
@ -3583,13 +3588,13 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
|
||||||
|
|
||||||
for (u32 i = 0; i < 2; i++)
|
for (u32 i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
MenuHeading(TinyString::FromFmt(FSUI_FSTR("Memory Card Port {}"), i + 1));
|
MenuHeading(TinyString::from_fmt(FSUI_FSTR("Memory Card Port {}"), i + 1));
|
||||||
|
|
||||||
const MemoryCardType default_type =
|
const MemoryCardType default_type =
|
||||||
(i == 0) ? Settings::DEFAULT_MEMORY_CARD_1_TYPE : Settings::DEFAULT_MEMORY_CARD_2_TYPE;
|
(i == 0) ? Settings::DEFAULT_MEMORY_CARD_1_TYPE : Settings::DEFAULT_MEMORY_CARD_2_TYPE;
|
||||||
DrawEnumSetting(
|
DrawEnumSetting(
|
||||||
bsi, TinyString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SD_CARD, "Memory Card {} Type")), i + 1),
|
bsi, TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_SD_CARD, "Memory Card {} Type")), i + 1),
|
||||||
SmallString::FromFmt(FSUI_FSTR("Sets which sort of memory card image will be used for slot {}."), i + 1),
|
SmallString::from_fmt(FSUI_FSTR("Sets which sort of memory card image will be used for slot {}."), i + 1),
|
||||||
"MemoryCards", type_keys[i], default_type, &Settings::ParseMemoryCardTypeName, &Settings::GetMemoryCardTypeName,
|
"MemoryCards", type_keys[i], default_type, &Settings::ParseMemoryCardTypeName, &Settings::GetMemoryCardTypeName,
|
||||||
&Settings::GetMemoryCardTypeDisplayName, MemoryCardType::Count);
|
&Settings::GetMemoryCardTypeDisplayName, MemoryCardType::Count);
|
||||||
|
|
||||||
|
@ -3605,7 +3610,7 @@ void FullscreenUI::DrawMemoryCardSettingsPage()
|
||||||
std::optional<const char*>((i == 0) ? "shared_card_1.mcd" : "shared_card_2.mcd")));
|
std::optional<const char*>((i == 0) ? "shared_card_1.mcd" : "shared_card_2.mcd")));
|
||||||
|
|
||||||
TinyString title;
|
TinyString title;
|
||||||
title.Fmt("{}##card_name_{}", FSUI_ICONSTR(ICON_FA_FILE, "Shared Card Name"), i);
|
title.fmt("{}##card_name_{}", FSUI_ICONSTR(ICON_FA_FILE, "Shared Card Name"), i);
|
||||||
if (MenuButtonWithValue(title,
|
if (MenuButtonWithValue(title,
|
||||||
FSUI_CSTR("The selected memory card image will be used in shared mode for this slot."),
|
FSUI_CSTR("The selected memory card image will be used in shared mode for this slot."),
|
||||||
path_value.has_value() ? path_value->c_str() : "Use Global Setting", is_shared))
|
path_value.has_value() ? path_value->c_str() : "Use Global Setting", is_shared))
|
||||||
|
@ -4075,7 +4080,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||||
PostProcessingStageInfo& si = s_postprocessing_stages[stage_index];
|
PostProcessingStageInfo& si = s_postprocessing_stages[stage_index];
|
||||||
|
|
||||||
ImGui::PushID(stage_index);
|
ImGui::PushID(stage_index);
|
||||||
str.Fmt(FSUI_FSTR("Stage {}: {}"), stage_index + 1, si.name);
|
str.fmt(FSUI_FSTR("Stage {}: {}"), stage_index + 1, si.name);
|
||||||
MenuHeading(str);
|
MenuHeading(str);
|
||||||
|
|
||||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_TIMES, "Remove From Chain"), FSUI_CSTR("Removes this shader from the chain.")))
|
if (MenuButton(FSUI_ICONSTR(ICON_FA_TIMES, "Remove From Chain"), FSUI_CSTR("Removes this shader from the chain.")))
|
||||||
|
@ -4109,7 +4114,7 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||||
case PostProcessing::ShaderOption::Type::Bool:
|
case PostProcessing::ShaderOption::Type::Bool:
|
||||||
{
|
{
|
||||||
bool value = (opt.value[0].int_value != 0);
|
bool value = (opt.value[0].int_value != 0);
|
||||||
tstr.Fmt(ICON_FA_COGS "{}", opt.ui_name);
|
tstr.fmt(ICON_FA_COGS "{}", opt.ui_name);
|
||||||
if (ToggleButton(tstr,
|
if (ToggleButton(tstr,
|
||||||
(opt.default_value[0].int_value != 0) ? FSUI_CSTR("Default: Enabled") :
|
(opt.default_value[0].int_value != 0) ? FSUI_CSTR("Default: Enabled") :
|
||||||
FSUI_CSTR("Default: Disabled"),
|
FSUI_CSTR("Default: Disabled"),
|
||||||
|
@ -4124,8 +4129,8 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||||
|
|
||||||
case PostProcessing::ShaderOption::Type::Float:
|
case PostProcessing::ShaderOption::Type::Float:
|
||||||
{
|
{
|
||||||
tstr.Fmt(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name);
|
tstr.fmt(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name);
|
||||||
str.Fmt(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].float_value,
|
str.fmt(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].float_value,
|
||||||
opt.default_value[0].float_value, opt.min_value[0].float_value, opt.max_value[0].float_value);
|
opt.default_value[0].float_value, opt.min_value[0].float_value, opt.max_value[0].float_value);
|
||||||
if (MenuButton(tstr, str))
|
if (MenuButton(tstr, str))
|
||||||
ImGui::OpenPopup(tstr);
|
ImGui::OpenPopup(tstr);
|
||||||
|
@ -4223,8 +4228,8 @@ void FullscreenUI::DrawPostProcessingSettingsPage()
|
||||||
|
|
||||||
case PostProcessing::ShaderOption::Type::Int:
|
case PostProcessing::ShaderOption::Type::Int:
|
||||||
{
|
{
|
||||||
tstr.Fmt(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name);
|
tstr.fmt(ICON_FA_RULER_VERTICAL "{}##{}", opt.ui_name, opt.name);
|
||||||
str.Fmt(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].int_value,
|
str.fmt(FSUI_FSTR("Value: {} | Default: {} | Minimum: {} | Maximum: {}"), opt.value[0].int_value,
|
||||||
opt.default_value[0].int_value, opt.min_value[0].int_value, opt.max_value[0].int_value);
|
opt.default_value[0].int_value, opt.min_value[0].int_value, opt.max_value[0].int_value);
|
||||||
if (MenuButton(tstr, str))
|
if (MenuButton(tstr, str))
|
||||||
ImGui::OpenPopup(tstr);
|
ImGui::OpenPopup(tstr);
|
||||||
|
@ -4489,17 +4494,17 @@ void FullscreenUI::DrawAchievementsSettingsPage()
|
||||||
if (bsi->ContainsValue("Cheevos", "Token"))
|
if (bsi->ContainsValue("Cheevos", "Token"))
|
||||||
{
|
{
|
||||||
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
||||||
ActiveButton(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_USER, "Username: {}")),
|
ActiveButton(SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_USER, "Username: {}")),
|
||||||
bsi->GetStringValue("Cheevos", "Username")),
|
bsi->GetStringValue("Cheevos", "Username")),
|
||||||
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||||
|
|
||||||
TinyString ts_string;
|
TinyString ts_string;
|
||||||
ts_string.AppendFmtString(
|
ts_string.fmt(
|
||||||
"{:%Y-%m-%d %H:%M:%S}",
|
"{:%Y-%m-%d %H:%M:%S}",
|
||||||
fmt::localtime(StringUtil::FromChars<u64>(bsi->GetStringValue("Cheevos", "LoginTimestamp", "0")).value_or(0)));
|
fmt::localtime(StringUtil::FromChars<u64>(bsi->GetStringValue("Cheevos", "LoginTimestamp", "0")).value_or(0)));
|
||||||
ActiveButton(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_CLOCK, "Login token generated on {}")),
|
ActiveButton(
|
||||||
ts_string.GetCharArray()),
|
SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_CLOCK, "Login token generated on {}")), ts_string),
|
||||||
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_KEY, "Logout"), FSUI_CSTR("Logs out of RetroAchievements.")))
|
if (MenuButton(FSUI_ICONSTR(ICON_FA_KEY, "Logout"), FSUI_CSTR("Logs out of RetroAchievements.")))
|
||||||
|
@ -4522,14 +4527,14 @@ void FullscreenUI::DrawAchievementsSettingsPage()
|
||||||
const auto lock = Achievements::GetLock();
|
const auto lock = Achievements::GetLock();
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
ImGui::PushStyleColor(ImGuiCol_TextDisabled, ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
||||||
ActiveButton(SmallString::FromFmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_BOOKMARK, "Game: {} ({})")),
|
ActiveButton(SmallString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_BOOKMARK, "Game: {} ({})")),
|
||||||
Achievements::GetGameID(), Achievements::GetGameTitle()),
|
Achievements::GetGameID(), Achievements::GetGameTitle()),
|
||||||
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
false, false, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||||
|
|
||||||
const std::string& rich_presence_string = Achievements::GetRichPresenceString();
|
const std::string& rich_presence_string = Achievements::GetRichPresenceString();
|
||||||
if (!rich_presence_string.empty())
|
if (!rich_presence_string.empty())
|
||||||
{
|
{
|
||||||
ActiveButton(SmallString::FromFmt(ICON_FA_MAP "{}", rich_presence_string), false, false,
|
ActiveButton(SmallString::from_fmt(ICON_FA_MAP "{}", rich_presence_string), false, false,
|
||||||
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4675,8 +4680,8 @@ void FullscreenUI::DrawPauseMenu()
|
||||||
const std::string& serial = System::GetGameSerial();
|
const std::string& serial = System::GetGameSerial();
|
||||||
|
|
||||||
if (!serial.empty())
|
if (!serial.empty())
|
||||||
buffer.Format("%s - ", serial.c_str());
|
buffer.fmt("{} - ", serial);
|
||||||
buffer.AppendString(Path::GetFileName(System::GetDiscPath()));
|
buffer.append(Path::GetFileName(System::GetDiscPath()));
|
||||||
|
|
||||||
const ImVec2 title_size(
|
const ImVec2 title_size(
|
||||||
g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits<float>::max(), -1.0f, title.c_str()));
|
g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits<float>::max(), -1.0f, title.c_str()));
|
||||||
|
@ -4712,8 +4717,8 @@ void FullscreenUI::DrawPauseMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawShadowedText(dl, g_large_font, title_pos, text_color, title.c_str());
|
DrawShadowedText(dl, g_large_font, title_pos, text_color, title.c_str(), title.c_str() + title.length());
|
||||||
DrawShadowedText(dl, g_medium_font, subtitle_pos, text_color, buffer);
|
DrawShadowedText(dl, g_medium_font, subtitle_pos, text_color, buffer.c_str(), buffer.end_ptr());
|
||||||
|
|
||||||
const ImVec2 image_min(display_size.x - LayoutScale(20.0f + 50.0f) - rp_height,
|
const ImVec2 image_min(display_size.x - LayoutScale(20.0f + 50.0f) - rp_height,
|
||||||
display_size.y - LayoutScale(20.0f + 50.0f) - rp_height);
|
display_size.y - LayoutScale(20.0f + 50.0f) - rp_height);
|
||||||
|
@ -4723,14 +4728,12 @@ void FullscreenUI::DrawPauseMenu()
|
||||||
|
|
||||||
// current time / play time
|
// current time / play time
|
||||||
{
|
{
|
||||||
buffer.Fmt("{:%X}", fmt::localtime(std::time(nullptr)));
|
buffer.fmt("{:%X}", fmt::localtime(std::time(nullptr)));
|
||||||
|
|
||||||
const ImVec2 time_size(g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits<float>::max(), -1.0f,
|
const ImVec2 time_size(g_large_font->CalcTextSizeA(g_large_font->FontSize, std::numeric_limits<float>::max(), -1.0f,
|
||||||
buffer.GetCharArray(),
|
buffer.c_str(), buffer.end_ptr()));
|
||||||
buffer.GetCharArray() + buffer.GetLength()));
|
|
||||||
const ImVec2 time_pos(display_size.x - LayoutScale(10.0f) - time_size.x, LayoutScale(10.0f));
|
const ImVec2 time_pos(display_size.x - LayoutScale(10.0f) - time_size.x, LayoutScale(10.0f));
|
||||||
DrawShadowedText(dl, g_large_font, time_pos, text_color, buffer.GetCharArray(),
|
DrawShadowedText(dl, g_large_font, time_pos, text_color, buffer.c_str(), buffer.end_ptr());
|
||||||
buffer.GetCharArray() + buffer.GetLength());
|
|
||||||
|
|
||||||
const std::string& serial = System::GetGameSerial();
|
const std::string& serial = System::GetGameSerial();
|
||||||
if (!serial.empty())
|
if (!serial.empty())
|
||||||
|
@ -4738,24 +4741,19 @@ void FullscreenUI::DrawPauseMenu()
|
||||||
const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(serial);
|
const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(serial);
|
||||||
const std::time_t session_time = static_cast<std::time_t>(System::GetSessionPlayedTime());
|
const std::time_t session_time = static_cast<std::time_t>(System::GetSessionPlayedTime());
|
||||||
|
|
||||||
buffer.Fmt(FSUI_FSTR("Session: {}"), GameList::FormatTimespan(session_time, true).GetStringView());
|
buffer.fmt(FSUI_FSTR("Session: {}"), GameList::FormatTimespan(session_time, true));
|
||||||
const ImVec2 session_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits<float>::max(),
|
const ImVec2 session_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits<float>::max(),
|
||||||
-1.0f, buffer.GetCharArray(),
|
-1.0f, buffer.c_str(), buffer.end_ptr()));
|
||||||
buffer.GetCharArray() + buffer.GetLength()));
|
|
||||||
const ImVec2 session_pos(display_size.x - LayoutScale(10.0f) - session_size.x,
|
const ImVec2 session_pos(display_size.x - LayoutScale(10.0f) - session_size.x,
|
||||||
time_pos.y + g_large_font->FontSize + LayoutScale(4.0f));
|
time_pos.y + g_large_font->FontSize + LayoutScale(4.0f));
|
||||||
DrawShadowedText(dl, g_medium_font, session_pos, text_color, buffer.GetCharArray(),
|
DrawShadowedText(dl, g_medium_font, session_pos, text_color, buffer.c_str(), buffer.end_ptr());
|
||||||
buffer.GetCharArray() + buffer.GetLength());
|
|
||||||
|
|
||||||
buffer.Fmt(FSUI_FSTR("All Time: {}"),
|
buffer.fmt(FSUI_FSTR("All Time: {}"), GameList::FormatTimespan(cached_played_time + session_time, true));
|
||||||
GameList::FormatTimespan(cached_played_time + session_time, true).GetStringView());
|
|
||||||
const ImVec2 total_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits<float>::max(),
|
const ImVec2 total_size(g_medium_font->CalcTextSizeA(g_medium_font->FontSize, std::numeric_limits<float>::max(),
|
||||||
-1.0f, buffer.GetCharArray(),
|
-1.0f, buffer.c_str(), buffer.end_ptr()));
|
||||||
buffer.GetCharArray() + buffer.GetLength()));
|
|
||||||
const ImVec2 total_pos(display_size.x - LayoutScale(10.0f) - total_size.x,
|
const ImVec2 total_pos(display_size.x - LayoutScale(10.0f) - total_size.x,
|
||||||
session_pos.y + g_medium_font->FontSize + LayoutScale(4.0f));
|
session_pos.y + g_medium_font->FontSize + LayoutScale(4.0f));
|
||||||
DrawShadowedText(dl, g_medium_font, total_pos, text_color, buffer.GetCharArray(),
|
DrawShadowedText(dl, g_medium_font, total_pos, text_color, buffer.c_str(), buffer.end_ptr());
|
||||||
buffer.GetCharArray() + buffer.GetLength());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5413,7 +5411,7 @@ void FullscreenUI::DrawResumeStateSelector()
|
||||||
TimeToPrintableString(&time, entry.timestamp);
|
TimeToPrintableString(&time, entry.timestamp);
|
||||||
ImGui::TextWrapped(
|
ImGui::TextWrapped(
|
||||||
FSUI_CSTR("A resume save state created at %s was found.\n\nDo you want to load this save and continue?"),
|
FSUI_CSTR("A resume save state created at %s was found.\n\nDo you want to load this save and continue?"),
|
||||||
time.GetCharArray());
|
time.c_str());
|
||||||
|
|
||||||
const GPUTexture* image = entry.preview_texture ? entry.preview_texture.get() : GetPlaceholderTexture().get();
|
const GPUTexture* image = entry.preview_texture ? entry.preview_texture.get() : GetPlaceholderTexture().get();
|
||||||
const float image_height = LayoutScale(250.0f);
|
const float image_height = LayoutScale(250.0f);
|
||||||
|
@ -5692,16 +5690,11 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||||
GPUTexture* cover_texture = GetGameListCover(entry);
|
GPUTexture* cover_texture = GetGameListCover(entry);
|
||||||
|
|
||||||
if (entry->serial.empty())
|
if (entry->serial.empty())
|
||||||
{
|
summary.fmt("{} - ", Settings::GetDiscRegionDisplayName(entry->region));
|
||||||
summary.Fmt("{} - ", Settings::GetDiscRegionDisplayName(entry->region));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
summary.fmt("{} - {} - ", entry->serial, Settings::GetDiscRegionDisplayName(entry->region));
|
||||||
summary.Fmt("{} - {} - ", entry->serial, Settings::GetDiscRegionDisplayName(entry->region));
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string_view filename(Path::GetFileName(entry->path));
|
summary.append(Path::GetFileName(entry->path));
|
||||||
summary.AppendString(filename);
|
|
||||||
|
|
||||||
const ImRect image_rect(
|
const ImRect image_rect(
|
||||||
CenterImage(ImRect(bb.Min, bb.Min + image_size), ImVec2(static_cast<float>(cover_texture->GetWidth()),
|
CenterImage(ImRect(bb.Min, bb.Min + image_size), ImVec2(static_cast<float>(cover_texture->GetWidth()),
|
||||||
|
@ -5720,12 +5713,11 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||||
entry->title.c_str() + entry->title.size(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
|
entry->title.c_str() + entry->title.size(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
if (!summary.IsEmpty())
|
if (!summary.empty())
|
||||||
{
|
{
|
||||||
ImGui::PushFont(g_medium_font);
|
ImGui::PushFont(g_medium_font);
|
||||||
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary.GetCharArray(),
|
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary.c_str(), summary.end_ptr(), nullptr,
|
||||||
summary.GetCharArray() + summary.GetLength(), nullptr, ImVec2(0.0f, 0.0f),
|
ImVec2(0.0f, 0.0f), &summary_bb);
|
||||||
&summary_bb);
|
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5832,10 +5824,8 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||||
ImGui::Text(" (%s)", GameDatabase::GetCompatibilityRatingDisplayName(selected_entry->compatibility));
|
ImGui::Text(" (%s)", GameDatabase::GetCompatibilityRatingDisplayName(selected_entry->compatibility));
|
||||||
|
|
||||||
// play time
|
// play time
|
||||||
ImGui::Text(FSUI_CSTR("Time Played: %s"),
|
ImGui::Text(FSUI_CSTR("Time Played: %s"), GameList::FormatTimespan(selected_entry->total_played_time).c_str());
|
||||||
GameList::FormatTimespan(selected_entry->total_played_time).GetCharArray());
|
ImGui::Text(FSUI_CSTR("Last Played: %s"), GameList::FormatTimestamp(selected_entry->last_played_time).c_str());
|
||||||
ImGui::Text(FSUI_CSTR("Last Played: %s"),
|
|
||||||
GameList::FormatTimestamp(selected_entry->last_played_time).GetCharArray());
|
|
||||||
|
|
||||||
// size
|
// size
|
||||||
ImGui::Text(FSUI_CSTR("Size: %.2f MB"), static_cast<float>(selected_entry->total_size) / 1048576.0f);
|
ImGui::Text(FSUI_CSTR("Size: %.2f MB"), static_cast<float>(selected_entry->total_size) / 1048576.0f);
|
||||||
|
@ -5941,11 +5931,10 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
|
||||||
const ImRect title_bb(ImVec2(bb.Min.x, bb.Min.y + image_height + title_spacing), bb.Max);
|
const ImRect title_bb(ImVec2(bb.Min.x, bb.Min.y + image_height + title_spacing), bb.Max);
|
||||||
const std::string_view title(
|
const std::string_view title(
|
||||||
std::string_view(entry->title).substr(0, (entry->title.length() > 31) ? 31 : std::string_view::npos));
|
std::string_view(entry->title).substr(0, (entry->title.length() > 31) ? 31 : std::string_view::npos));
|
||||||
draw_title.Fmt("{}{}", title, (title.length() == entry->title.length()) ? "" : "...");
|
draw_title.fmt("{}{}", title, (title.length() == entry->title.length()) ? "" : "...");
|
||||||
ImGui::PushFont(g_medium_font);
|
ImGui::PushFont(g_medium_font);
|
||||||
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.GetCharArray(),
|
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.end_ptr(), nullptr,
|
||||||
draw_title.GetCharArray() + draw_title.GetLength(), nullptr, ImVec2(0.5f, 0.0f),
|
ImVec2(0.5f, 0.0f), &title_bb);
|
||||||
&title_bb);
|
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
|
@ -6073,7 +6062,7 @@ void FullscreenUI::DrawGameListSettingsPage(const ImVec2& heading_size)
|
||||||
|
|
||||||
for (const auto& it : s_game_list_directories_cache)
|
for (const auto& it : s_game_list_directories_cache)
|
||||||
{
|
{
|
||||||
if (MenuButton(SmallString::FromFmt(ICON_FA_FOLDER "{}", it.first),
|
if (MenuButton(SmallString::from_fmt(ICON_FA_FOLDER "{}", it.first),
|
||||||
it.second ? FSUI_CSTR("Scanning Subdirectories") : FSUI_CSTR("Not Scanning Subdirectories")))
|
it.second ? FSUI_CSTR("Scanning Subdirectories") : FSUI_CSTR("Not Scanning Subdirectories")))
|
||||||
{
|
{
|
||||||
ImGuiFullscreen::ChoiceDialogOptions options = {
|
ImGuiFullscreen::ChoiceDialogOptions options = {
|
||||||
|
@ -6609,8 +6598,7 @@ void FullscreenUI::ProgressCallback::Redraw(bool force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_last_progress_percent = percent;
|
m_last_progress_percent = percent;
|
||||||
ImGuiFullscreen::UpdateBackgroundProgressDialog(
|
ImGuiFullscreen::UpdateBackgroundProgressDialog(m_name.c_str(), m_status_text, 0, 100, percent);
|
||||||
m_name.c_str(), std::string(m_status_text.GetCharArray(), m_status_text.GetLength()), 0, 100, percent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FullscreenUI::ProgressCallback::DisplayError(const char* message)
|
void FullscreenUI::ProgressCallback::DisplayError(const char* message)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class String;
|
class SmallStringBase;
|
||||||
|
|
||||||
struct Settings;
|
struct Settings;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ void ReturnToPreviousWindow();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Render();
|
void Render();
|
||||||
void InvalidateCoverCache();
|
void InvalidateCoverCache();
|
||||||
void TimeToPrintableString(String* str, time_t t);
|
void TimeToPrintableString(SmallStringBase* str, time_t t);
|
||||||
|
|
||||||
// Returns true if the message has been dismissed.
|
// Returns true if the message has been dismissed.
|
||||||
bool DrawErrorWindow(const char* message);
|
bool DrawErrorWindow(const char* message);
|
||||||
|
|
|
@ -463,18 +463,19 @@ void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_mes
|
||||||
if ((supported_controllers & BIT_FOR(supported_ctype)) == 0)
|
if ((supported_controllers & BIT_FOR(supported_ctype)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!supported_controller_string.IsEmpty())
|
if (!supported_controller_string.empty())
|
||||||
supported_controller_string.AppendString(", ");
|
supported_controller_string.append(", ");
|
||||||
|
|
||||||
supported_controller_string.AppendString(Settings::GetControllerTypeDisplayName(supported_ctype));
|
supported_controller_string.append(Settings::GetControllerTypeDisplayName(supported_ctype));
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::AddKeyedFormattedOSDMessage(
|
Host::AddKeyedOSDMessage(
|
||||||
"gamedb_controller_unsupported", 30.0f,
|
"gamedb_controller_unsupported",
|
||||||
TRANSLATE("OSDMessage", "Controller in port %u (%s) is not supported for %s.\nSupported controllers: "
|
fmt::format(
|
||||||
"%s\nPlease configure a supported controller from the list above."),
|
TRANSLATE_FS("OSDMessage", "Controller in port {0} ({1}) is not supported for {2}.\nSupported controllers: "
|
||||||
i + 1u, Settings::GetControllerTypeDisplayName(ctype), System::GetGameTitle().c_str(),
|
"{3}\nPlease configure a supported controller from the list above."),
|
||||||
supported_controller_string.GetCharArray());
|
i + 1u, Settings::GetControllerTypeDisplayName(ctype), System::GetGameTitle(), supported_controller_string),
|
||||||
|
Host::OSD_CRITICAL_ERROR_DURATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -994,7 +994,7 @@ TinyString GameList::FormatTimestamp(std::time_t timestamp)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
std::strftime(buf, std::size(buf), "%x", &ttime);
|
std::strftime(buf, std::size(buf), "%x", &ttime);
|
||||||
ret.Assign(buf);
|
ret.assign(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,22 +1011,22 @@ TinyString GameList::FormatTimespan(std::time_t timespan, bool long_format)
|
||||||
if (!long_format)
|
if (!long_format)
|
||||||
{
|
{
|
||||||
if (hours >= 100)
|
if (hours >= 100)
|
||||||
ret.Fmt(TRANSLATE_FS("GameList", "{}h {}m"), hours, minutes);
|
ret.fmt(TRANSLATE_FS("GameList", "{}h {}m"), hours, minutes);
|
||||||
else if (hours > 0)
|
else if (hours > 0)
|
||||||
ret.Fmt(TRANSLATE_FS("GameList", "{}h {}m {}s"), hours, minutes, seconds);
|
ret.fmt(TRANSLATE_FS("GameList", "{}h {}m {}s"), hours, minutes, seconds);
|
||||||
else if (minutes > 0)
|
else if (minutes > 0)
|
||||||
ret.Fmt(TRANSLATE_FS("GameList", "{}m {}s"), minutes, seconds);
|
ret.fmt(TRANSLATE_FS("GameList", "{}m {}s"), minutes, seconds);
|
||||||
else if (seconds > 0)
|
else if (seconds > 0)
|
||||||
ret.Fmt(TRANSLATE_FS("GameList", "{}s"), seconds);
|
ret.fmt(TRANSLATE_FS("GameList", "{}s"), seconds);
|
||||||
else
|
else
|
||||||
ret = TRANSLATE_SV("GameList", "None");
|
ret = TRANSLATE_SV("GameList", "None");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (hours > 0)
|
if (hours > 0)
|
||||||
ret = fmt::format(TRANSLATE_FS("GameList", "{} hours"), hours);
|
ret.fmt(TRANSLATE_FS("GameList", "{} hours"), hours);
|
||||||
else
|
else
|
||||||
ret = fmt::format(TRANSLATE_FS("GameList", "{} minutes"), minutes);
|
ret.fmt(TRANSLATE_FS("GameList", "{} minutes"), minutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include "util/cd_image.h"
|
#include "util/cd_image.h"
|
||||||
|
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
|
@ -180,8 +180,8 @@ bool GPU::HandleUnknownGP0Command()
|
||||||
|
|
||||||
SmallString dump;
|
SmallString dump;
|
||||||
for (u32 i = 0; i < m_fifo.GetSize(); i++)
|
for (u32 i = 0; i < m_fifo.GetSize(); i++)
|
||||||
dump.AppendFormattedString("%s0x%08X", (i > 0) ? " " : "", FifoPeek(i));
|
dump.append_fmt("{}{:08X}", (i > 0) ? " " : "", FifoPeek(i));
|
||||||
Log_ErrorPrintf("FIFO: %s", dump.GetCharArray());
|
Log_ErrorPrintf("FIFO: %s", dump.c_str());
|
||||||
|
|
||||||
m_fifo.RemoveOne();
|
m_fifo.RemoveOne();
|
||||||
EndCommand();
|
EndCommand();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "util/host.h"
|
#include "util/host.h"
|
||||||
|
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
Log_SetChannel(HostInterfaceProgressCallback);
|
Log_SetChannel(HostInterfaceProgressCallback);
|
||||||
|
|
||||||
HostInterfaceProgressCallback::HostInterfaceProgressCallback() : BaseProgressCallback() {}
|
HostInterfaceProgressCallback::HostInterfaceProgressCallback() : BaseProgressCallback()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::PushState()
|
void HostInterfaceProgressCallback::PushState()
|
||||||
{
|
{
|
||||||
|
@ -64,7 +66,8 @@ void HostInterfaceProgressCallback::Redraw(bool force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_last_progress_percent = percent;
|
m_last_progress_percent = percent;
|
||||||
Host::DisplayLoadingScreen(m_status_text, 0, static_cast<int>(m_progress_range), static_cast<int>(m_progress_value));
|
Host::DisplayLoadingScreen(m_status_text.c_str(), 0, static_cast<int>(m_progress_range),
|
||||||
|
static_cast<int>(m_progress_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::DisplayError(const char* message)
|
void HostInterfaceProgressCallback::DisplayError(const char* message)
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
Log_SetChannel(ImGuiManager);
|
Log_SetChannel(ImGuiManager);
|
||||||
|
|
||||||
namespace ImGuiManager {
|
namespace ImGuiManager {
|
||||||
static void FormatProcessorStat(String& text, double usage, double time);
|
static void FormatProcessorStat(SmallStringBase& text, double usage, double time);
|
||||||
static void DrawPerformanceOverlay();
|
static void DrawPerformanceOverlay();
|
||||||
static void DrawEnhancementsOverlay();
|
static void DrawEnhancementsOverlay();
|
||||||
static void DrawInputsOverlay();
|
static void DrawInputsOverlay();
|
||||||
|
@ -179,12 +179,12 @@ void Host::DisplayLoadingScreen(const char* message, int progress_min /*= -1*/,
|
||||||
ImGui::TextUnformatted(message);
|
ImGui::TextUnformatted(message);
|
||||||
|
|
||||||
TinyString buf;
|
TinyString buf;
|
||||||
buf.Fmt("{}/{}", progress_value, progress_max);
|
buf.fmt("{}/{}", progress_value, progress_max);
|
||||||
|
|
||||||
const ImVec2 prog_size = ImGui::CalcTextSize(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength());
|
const ImVec2 prog_size = ImGui::CalcTextSize(buf.c_str(), buf.end_ptr());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(width - padding_and_rounding - prog_size.x);
|
ImGui::SetCursorPosX(width - padding_and_rounding - prog_size.x);
|
||||||
ImGui::TextUnformatted(buf.GetCharArray(), buf.GetCharArray() + buf.GetLength());
|
ImGui::TextUnformatted(buf.c_str(), buf.end_ptr());
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f);
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5.0f);
|
||||||
|
|
||||||
ImGui::ProgressBar(static_cast<float>(progress_value) / static_cast<float>(progress_max - progress_min),
|
ImGui::ProgressBar(static_cast<float>(progress_value) / static_cast<float>(progress_max - progress_min),
|
||||||
|
@ -259,15 +259,15 @@ void ImGuiManager::RenderOverlayWindows()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiManager::FormatProcessorStat(String& text, double usage, double time)
|
void ImGuiManager::FormatProcessorStat(SmallStringBase& text, double usage, double time)
|
||||||
{
|
{
|
||||||
// Some values, such as GPU (and even CPU to some extent) can be out of phase with the wall clock,
|
// Some values, such as GPU (and even CPU to some extent) can be out of phase with the wall clock,
|
||||||
// which the processor time is divided by to get a utilization percentage. Let's clamp it at 100%,
|
// which the processor time is divided by to get a utilization percentage. Let's clamp it at 100%,
|
||||||
// so that people don't get confused, and remove the decimal places when it's there while we're at it.
|
// so that people don't get confused, and remove the decimal places when it's there while we're at it.
|
||||||
if (usage >= 99.95)
|
if (usage >= 99.95)
|
||||||
text.AppendFmtString("100% ({:.2f}ms)", time);
|
text.append_fmt("100% ({:.2f}ms)", time);
|
||||||
else
|
else
|
||||||
text.AppendFmtString("{:.1f}% ({:.2f}ms)", usage, time);
|
text.append_fmt("{:.1f}% ({:.2f}ms)", usage, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiManager::DrawPerformanceOverlay()
|
void ImGuiManager::DrawPerformanceOverlay()
|
||||||
|
@ -301,7 +301,7 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
dl->AddText( \
|
dl->AddText( \
|
||||||
font, font->FontSize, \
|
font, font->FontSize, \
|
||||||
ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x + shadow_offset, position_y + shadow_offset), \
|
ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x + shadow_offset, position_y + shadow_offset), \
|
||||||
IM_COL32(0, 0, 0, 100), text, text.GetCharArray() + text.GetLength()); \
|
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr()); \
|
||||||
dl->AddText(font, font->FontSize, ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x, position_y), color, \
|
dl->AddText(font, font->FontSize, ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x, position_y), color, \
|
||||||
(text)); \
|
(text)); \
|
||||||
position_y += text_size.y + spacing; \
|
position_y += text_size.y + spacing; \
|
||||||
|
@ -313,22 +313,22 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
const float speed = System::GetEmulationSpeed();
|
const float speed = System::GetEmulationSpeed();
|
||||||
if (g_settings.display_show_fps)
|
if (g_settings.display_show_fps)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("G: {:.2f} | V: {:.2f}", System::GetFPS(), System::GetVPS());
|
text.append_fmt("G: {:.2f} | V: {:.2f}", System::GetFPS(), System::GetVPS());
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if (g_settings.display_show_speed)
|
if (g_settings.display_show_speed)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}{}%", first ? "" : " | ", static_cast<u32>(std::round(speed)));
|
text.append_fmt("{}{}%", first ? "" : " | ", static_cast<u32>(std::round(speed)));
|
||||||
|
|
||||||
const float target_speed = System::GetTargetSpeed();
|
const float target_speed = System::GetTargetSpeed();
|
||||||
if (target_speed <= 0.0f)
|
if (target_speed <= 0.0f)
|
||||||
text.AppendString(" (Max)");
|
text.append(" (Max)");
|
||||||
else
|
else
|
||||||
text.AppendFmtString(" ({:.0f}%)", target_speed * 100.0f);
|
text.append_fmt(" ({:.0f}%)", target_speed * 100.0f);
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if (!text.IsEmpty())
|
if (!text.empty())
|
||||||
{
|
{
|
||||||
ImU32 color;
|
ImU32 color;
|
||||||
if (speed < 95.0f)
|
if (speed < 95.0f)
|
||||||
|
@ -347,65 +347,63 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
const auto [effective_width, effective_height] = g_gpu->GetEffectiveDisplayResolution();
|
const auto [effective_width, effective_height] = g_gpu->GetEffectiveDisplayResolution();
|
||||||
const bool interlaced = g_gpu->IsInterlacedDisplayEnabled();
|
const bool interlaced = g_gpu->IsInterlacedDisplayEnabled();
|
||||||
const bool pal = g_gpu->IsInPALMode();
|
const bool pal = g_gpu->IsInPALMode();
|
||||||
text.Fmt("{}x{} {} {}", effective_width, effective_height, pal ? "PAL" : "NTSC",
|
text.fmt("{}x{} {} {}", effective_width, effective_height, pal ? "PAL" : "NTSC",
|
||||||
interlaced ? "Interlaced" : "Progressive");
|
interlaced ? "Interlaced" : "Progressive");
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_settings.display_show_cpu)
|
if (g_settings.display_show_cpu)
|
||||||
{
|
{
|
||||||
text.Clear();
|
text.fmt("{:.2f}ms | {:.2f}ms | {:.2f}ms", System::GetMinimumFrameTime(), System::GetAverageFrameTime(),
|
||||||
text.AppendFmtString("{:.2f}ms | {:.2f}ms | {:.2f}ms", System::GetMinimumFrameTime(),
|
System::GetMaximumFrameTime());
|
||||||
System::GetAverageFrameTime(), System::GetMaximumFrameTime());
|
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
|
|
||||||
text.Clear();
|
|
||||||
if (g_settings.cpu_overclock_active || (!g_settings.IsUsingRecompiler() || g_settings.cpu_recompiler_icache ||
|
if (g_settings.cpu_overclock_active || (!g_settings.IsUsingRecompiler() || g_settings.cpu_recompiler_icache ||
|
||||||
g_settings.cpu_recompiler_memory_exceptions))
|
g_settings.cpu_recompiler_memory_exceptions))
|
||||||
{
|
{
|
||||||
first = true;
|
first = true;
|
||||||
text.AppendString("CPU[");
|
text.assign("CPU[");
|
||||||
if (g_settings.cpu_overclock_active)
|
if (g_settings.cpu_overclock_active)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}", g_settings.GetCPUOverclockPercent());
|
text.append_fmt("{}", g_settings.GetCPUOverclockPercent());
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if (g_settings.cpu_execution_mode == CPUExecutionMode::Interpreter)
|
if (g_settings.cpu_execution_mode == CPUExecutionMode::Interpreter)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}{}", first ? "" : "/", "I");
|
text.append_fmt("{}{}", first ? "" : "/", "I");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else if (g_settings.cpu_execution_mode == CPUExecutionMode::CachedInterpreter)
|
else if (g_settings.cpu_execution_mode == CPUExecutionMode::CachedInterpreter)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}{}", first ? "" : "/", "CI");
|
text.append_fmt("{}{}", first ? "" : "/", "CI");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_settings.cpu_recompiler_icache)
|
if (g_settings.cpu_recompiler_icache)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}{}", first ? "" : "/", "IC");
|
text.append_fmt("{}{}", first ? "" : "/", "IC");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if (g_settings.cpu_recompiler_memory_exceptions)
|
if (g_settings.cpu_recompiler_memory_exceptions)
|
||||||
{
|
{
|
||||||
text.AppendFmtString("{}{}", first ? "" : "/", "ME");
|
text.append_fmt("{}{}", first ? "" : "/", "ME");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text.AppendString("]: ");
|
text.append("]: ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text.Assign("CPU: ");
|
text.assign("CPU: ");
|
||||||
}
|
}
|
||||||
FormatProcessorStat(text, System::GetCPUThreadUsage(), System::GetCPUThreadAverageTime());
|
FormatProcessorStat(text, System::GetCPUThreadUsage(), System::GetCPUThreadAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
|
|
||||||
if (g_gpu->GetSWThread())
|
if (g_gpu->GetSWThread())
|
||||||
{
|
{
|
||||||
text.Assign("SW: ");
|
text.assign("SW: ");
|
||||||
FormatProcessorStat(text, System::GetSWThreadUsage(), System::GetSWThreadAverageTime());
|
FormatProcessorStat(text, System::GetSWThreadUsage(), System::GetSWThreadAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
@ -414,8 +412,7 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
{
|
{
|
||||||
AudioStream* stream = g_spu.GetOutputStream();
|
AudioStream* stream = g_spu.GetOutputStream();
|
||||||
const u32 frames = stream->GetBufferedFramesRelaxed();
|
const u32 frames = stream->GetBufferedFramesRelaxed();
|
||||||
text.Clear();
|
text.fmt("Audio: {:<4u}f/{:<3u}ms", frames, AudioStream::GetMSForBufferSize(stream->GetSampleRate(), frames));
|
||||||
text.Fmt("Audio: {:<4u}f/{:<3u}ms", frames, AudioStream::GetMSForBufferSize(stream->GetSampleRate(), frames));
|
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -423,7 +420,7 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
|
|
||||||
if (g_settings.display_show_gpu && g_gpu_device->IsGPUTimingEnabled())
|
if (g_settings.display_show_gpu && g_gpu_device->IsGPUTimingEnabled())
|
||||||
{
|
{
|
||||||
text.Assign("GPU: ");
|
text.assign("GPU: ");
|
||||||
FormatProcessorStat(text, System::GetGPUUsage(), System::GetGPUAverageTime());
|
FormatProcessorStat(text, System::GetGPUUsage(), System::GetGPUAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
@ -433,7 +430,7 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
const bool rewinding = System::IsRewinding();
|
const bool rewinding = System::IsRewinding();
|
||||||
if (rewinding || System::IsFastForwardEnabled() || System::IsTurboEnabled())
|
if (rewinding || System::IsFastForwardEnabled() || System::IsTurboEnabled())
|
||||||
{
|
{
|
||||||
text.Assign(rewinding ? ICON_FA_FAST_BACKWARD : ICON_FA_FAST_FORWARD);
|
text.assign(rewinding ? ICON_FA_FAST_BACKWARD : ICON_FA_FAST_FORWARD);
|
||||||
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,25 +474,21 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
||||||
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
||||||
|
|
||||||
text.Clear();
|
text.fmt("{:.1f} ms", max);
|
||||||
text.AppendFmtString("{:.1f} ms", max);
|
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||||
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.GetCharArray(),
|
|
||||||
text.GetCharArray() + text.GetLength());
|
|
||||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset, wpos.y + shadow_offset),
|
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset, wpos.y + shadow_offset),
|
||||||
IM_COL32(0, 0, 0, 100), text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y), IM_COL32(255, 255, 255, 255),
|
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y), IM_COL32(255, 255, 255, 255),
|
||||||
text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
text.c_str(), text.end_ptr());
|
||||||
|
|
||||||
text.Clear();
|
text.fmt("{:.1f} ms", min);
|
||||||
text.AppendFmtString("{:.1f} ms", min);
|
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||||
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.GetCharArray(),
|
|
||||||
text.GetCharArray() + text.GetLength());
|
|
||||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset,
|
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset,
|
||||||
wpos.y + history_size.y - fixed_font->FontSize + shadow_offset),
|
wpos.y + history_size.y - fixed_font->FontSize + shadow_offset),
|
||||||
IM_COL32(0, 0, 0, 100), text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||||
win_dl->AddText(
|
win_dl->AddText(
|
||||||
ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y + history_size.y - fixed_font->FontSize),
|
ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y + history_size.y - fixed_font->FontSize),
|
||||||
IM_COL32(255, 255, 255, 255), text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
IM_COL32(255, 255, 255, 255), text.c_str(), text.end_ptr());
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -506,7 +499,7 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
else if (g_settings.display_show_status_indicators && state == System::State::Paused &&
|
else if (g_settings.display_show_status_indicators && state == System::State::Paused &&
|
||||||
!FullscreenUI::HasActiveWindow())
|
!FullscreenUI::HasActiveWindow())
|
||||||
{
|
{
|
||||||
text.Assign(ICON_FA_PAUSE);
|
text.assign(ICON_FA_PAUSE);
|
||||||
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,58 +509,57 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||||
void ImGuiManager::DrawEnhancementsOverlay()
|
void ImGuiManager::DrawEnhancementsOverlay()
|
||||||
{
|
{
|
||||||
LargeString text;
|
LargeString text;
|
||||||
text.AppendFmtString("{} {}-{}", Settings::GetConsoleRegionName(System::GetRegion()),
|
text.append_fmt("{} {}-{}", Settings::GetConsoleRegionName(System::GetRegion()),
|
||||||
GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()),
|
GPUDevice::RenderAPIToString(g_gpu_device->GetRenderAPI()),
|
||||||
g_gpu->IsHardwareRenderer() ? "HW" : "SW");
|
g_gpu->IsHardwareRenderer() ? "HW" : "SW");
|
||||||
|
|
||||||
if (g_settings.rewind_enable)
|
if (g_settings.rewind_enable)
|
||||||
text.AppendFormattedString(" RW=%g/%u", g_settings.rewind_save_frequency, g_settings.rewind_save_slots);
|
text.append_fmt(" RW={}/{}", g_settings.rewind_save_frequency, g_settings.rewind_save_slots);
|
||||||
if (g_settings.IsRunaheadEnabled())
|
if (g_settings.IsRunaheadEnabled())
|
||||||
text.AppendFormattedString(" RA=%u", g_settings.runahead_frames);
|
text.append_fmt(" RA={}", g_settings.runahead_frames);
|
||||||
|
|
||||||
if (g_settings.cpu_overclock_active)
|
if (g_settings.cpu_overclock_active)
|
||||||
text.AppendFormattedString(" CPU=%u%%", g_settings.GetCPUOverclockPercent());
|
text.append_fmt(" CPU={}%", g_settings.GetCPUOverclockPercent());
|
||||||
if (g_settings.enable_8mb_ram)
|
if (g_settings.enable_8mb_ram)
|
||||||
text.AppendString(" 8MB");
|
text.append(" 8MB");
|
||||||
if (g_settings.cdrom_read_speedup != 1)
|
if (g_settings.cdrom_read_speedup != 1)
|
||||||
text.AppendFormattedString(" CDR=%ux", g_settings.cdrom_read_speedup);
|
text.append_fmt(" CDR={}x", g_settings.cdrom_read_speedup);
|
||||||
if (g_settings.cdrom_seek_speedup != 1)
|
if (g_settings.cdrom_seek_speedup != 1)
|
||||||
text.AppendFormattedString(" CDS=%ux", g_settings.cdrom_seek_speedup);
|
text.append_fmt(" CDS={}x", g_settings.cdrom_seek_speedup);
|
||||||
if (g_settings.gpu_resolution_scale != 1)
|
if (g_settings.gpu_resolution_scale != 1)
|
||||||
text.AppendFormattedString(" IR=%ux", g_settings.gpu_resolution_scale);
|
text.append_fmt(" IR={}x", g_settings.gpu_resolution_scale);
|
||||||
if (g_settings.gpu_multisamples != 1)
|
if (g_settings.gpu_multisamples != 1)
|
||||||
{
|
{
|
||||||
text.AppendFormattedString(" %ux%s", g_settings.gpu_multisamples,
|
text.append_fmt(" {}x{}", g_settings.gpu_multisamples, g_settings.gpu_per_sample_shading ? "SSAA" : "MSAA");
|
||||||
g_settings.gpu_per_sample_shading ? "SSAA" : "MSAA");
|
|
||||||
}
|
}
|
||||||
if (g_settings.gpu_true_color)
|
if (g_settings.gpu_true_color)
|
||||||
text.AppendString(" TrueCol");
|
text.append(" TrueCol");
|
||||||
if (g_settings.gpu_disable_interlacing)
|
if (g_settings.gpu_disable_interlacing)
|
||||||
text.AppendString(" ForceProg");
|
text.append(" ForceProg");
|
||||||
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
|
if (g_settings.gpu_force_ntsc_timings && System::GetRegion() == ConsoleRegion::PAL)
|
||||||
text.AppendString(" PAL60");
|
text.append(" PAL60");
|
||||||
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
if (g_settings.gpu_texture_filter != GPUTextureFilter::Nearest)
|
||||||
text.AppendFormattedString(" %s", Settings::GetTextureFilterName(g_settings.gpu_texture_filter));
|
text.append_fmt(" {}", Settings::GetTextureFilterName(g_settings.gpu_texture_filter));
|
||||||
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio != DisplayAspectRatio::Auto &&
|
if (g_settings.gpu_widescreen_hack && g_settings.display_aspect_ratio != DisplayAspectRatio::Auto &&
|
||||||
g_settings.display_aspect_ratio != DisplayAspectRatio::R4_3)
|
g_settings.display_aspect_ratio != DisplayAspectRatio::R4_3)
|
||||||
{
|
{
|
||||||
text.AppendString(" WSHack");
|
text.append(" WSHack");
|
||||||
}
|
}
|
||||||
if (g_settings.gpu_pgxp_enable)
|
if (g_settings.gpu_pgxp_enable)
|
||||||
{
|
{
|
||||||
text.AppendString(" PGXP");
|
text.append(" PGXP");
|
||||||
if (g_settings.gpu_pgxp_culling)
|
if (g_settings.gpu_pgxp_culling)
|
||||||
text.AppendString("/Cull");
|
text.append("/Cull");
|
||||||
if (g_settings.gpu_pgxp_texture_correction)
|
if (g_settings.gpu_pgxp_texture_correction)
|
||||||
text.AppendString("/Tex");
|
text.append("/Tex");
|
||||||
if (g_settings.gpu_pgxp_color_correction)
|
if (g_settings.gpu_pgxp_color_correction)
|
||||||
text.AppendString("/Col");
|
text.append("/Col");
|
||||||
if (g_settings.gpu_pgxp_vertex_cache)
|
if (g_settings.gpu_pgxp_vertex_cache)
|
||||||
text.AppendString("/VC");
|
text.append("/VC");
|
||||||
if (g_settings.gpu_pgxp_cpu)
|
if (g_settings.gpu_pgxp_cpu)
|
||||||
text.AppendString("/CPU");
|
text.append("/CPU");
|
||||||
if (g_settings.gpu_pgxp_depth_buffer)
|
if (g_settings.gpu_pgxp_depth_buffer)
|
||||||
text.AppendString("/Depth");
|
text.append("/Depth");
|
||||||
}
|
}
|
||||||
|
|
||||||
const float scale = ImGuiManager::GetGlobalScale();
|
const float scale = ImGuiManager::GetGlobalScale();
|
||||||
|
@ -577,13 +569,13 @@ void ImGuiManager::DrawEnhancementsOverlay()
|
||||||
const float position_y = ImGui::GetIO().DisplaySize.y - margin - font->FontSize;
|
const float position_y = ImGui::GetIO().DisplaySize.y - margin - font->FontSize;
|
||||||
|
|
||||||
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||||
ImVec2 text_size = font->CalcTextSizeA(font->FontSize, std::numeric_limits<float>::max(), -1.0f, text,
|
ImVec2 text_size = font->CalcTextSizeA(font->FontSize, std::numeric_limits<float>::max(), -1.0f, text.c_str(),
|
||||||
text.GetCharArray() + text.GetLength(), nullptr);
|
text.end_ptr(), nullptr);
|
||||||
dl->AddText(font, font->FontSize,
|
dl->AddText(font, font->FontSize,
|
||||||
ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x + shadow_offset, position_y + shadow_offset),
|
ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x + shadow_offset, position_y + shadow_offset),
|
||||||
IM_COL32(0, 0, 0, 100), text, text.GetCharArray() + text.GetLength());
|
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||||
dl->AddText(font, font->FontSize, ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x, position_y),
|
dl->AddText(font, font->FontSize, ImVec2(ImGui::GetIO().DisplaySize.x - margin - text_size.x, position_y),
|
||||||
IM_COL32(255, 255, 255, 255), text, text.GetCharArray() + text.GetLength());
|
IM_COL32(255, 255, 255, 255), text.c_str(), text.end_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiManager::DrawInputsOverlay()
|
void ImGuiManager::DrawInputsOverlay()
|
||||||
|
@ -612,7 +604,7 @@ void ImGuiManager::DrawInputsOverlay()
|
||||||
|
|
||||||
const ImVec4 clip_rect(current_x, current_y, display_size.x - margin, display_size.y - margin);
|
const ImVec4 clip_rect(current_x, current_y, display_size.x - margin, display_size.y - margin);
|
||||||
|
|
||||||
LargeString text;
|
SmallString text;
|
||||||
|
|
||||||
for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++)
|
for (u32 port = 0; port < NUM_CONTROLLER_AND_CARD_PORTS; port++)
|
||||||
{
|
{
|
||||||
|
@ -625,7 +617,7 @@ void ImGuiManager::DrawInputsOverlay()
|
||||||
if (!cinfo)
|
if (!cinfo)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
text.Fmt("P{} |", port + 1u);
|
text.fmt("P{} |", port + 1u);
|
||||||
|
|
||||||
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
|
for (const Controller::ControllerBindingInfo& bi : cinfo->bindings)
|
||||||
{
|
{
|
||||||
|
@ -637,9 +629,9 @@ void ImGuiManager::DrawInputsOverlay()
|
||||||
// axes are always shown
|
// axes are always shown
|
||||||
const float value = controller->GetBindState(bi.bind_index);
|
const float value = controller->GetBindState(bi.bind_index);
|
||||||
if (value >= (254.0f / 255.0f))
|
if (value >= (254.0f / 255.0f))
|
||||||
text.AppendFmtString(" {}", bi.name);
|
text.append_fmt(" {}", bi.name);
|
||||||
else if (value > (1.0f / 255.0f))
|
else if (value > (1.0f / 255.0f))
|
||||||
text.AppendFmtString(" {}: {:.2f}", bi.name, value);
|
text.append_fmt(" {}: {:.2f}", bi.name, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -648,7 +640,7 @@ void ImGuiManager::DrawInputsOverlay()
|
||||||
// buttons only shown when active
|
// buttons only shown when active
|
||||||
const float value = controller->GetBindState(bi.bind_index);
|
const float value = controller->GetBindState(bi.bind_index);
|
||||||
if (value >= 0.5f)
|
if (value >= 0.5f)
|
||||||
text.AppendFmtString(" {}", bi.name);
|
text.append_fmt(" {}", bi.name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -662,9 +654,9 @@ void ImGuiManager::DrawInputsOverlay()
|
||||||
}
|
}
|
||||||
|
|
||||||
dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color,
|
dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color,
|
||||||
text.GetCharArray(), text.GetCharArray() + text.GetLength(), 0.0f, &clip_rect);
|
text.c_str(), text.end_ptr(), 0.0f, &clip_rect);
|
||||||
dl->AddText(font, font->FontSize, ImVec2(current_x, current_y), text_color, text.GetCharArray(),
|
dl->AddText(font, font->FontSize, ImVec2(current_x, current_y), text_color, text.c_str(), text.end_ptr(), 0.0f,
|
||||||
text.GetCharArray() + text.GetLength(), 0.0f, &clip_rect);
|
&clip_rect);
|
||||||
|
|
||||||
current_y += font->FontSize + spacing;
|
current_y += font->FontSize + spacing;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ static bool LoadLibraryPSF(const char* path, bool use_pc_sp, u32 depth = 0)
|
||||||
u32 lib_counter = 2;
|
u32 lib_counter = 2;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
lib_name = file.GetTagString(TinyString::FromFormat("_lib%u", lib_counter++));
|
lib_name = file.GetTagString(TinyString::from_fmt("_lib{}", lib_counter++));
|
||||||
if (!lib_name.has_value())
|
if (!lib_name.has_value())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -101,34 +101,6 @@ bool Settings::HasAnyPerGameMemoryCards() const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> Settings::GeneratePortLabels() const
|
|
||||||
{
|
|
||||||
static constexpr std::array<std::array<bool, NUM_MULTITAPS>, static_cast<size_t>(MultitapMode::Count)>
|
|
||||||
multitap_enabled_on_port = {{{false, false}, {true, false}, {false, true}, {true, true}}};
|
|
||||||
|
|
||||||
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> labels;
|
|
||||||
|
|
||||||
u32 logical_port = 0;
|
|
||||||
for (u32 physical_port = 0; physical_port < NUM_MULTITAPS; physical_port++)
|
|
||||||
{
|
|
||||||
if (multitap_enabled_on_port[static_cast<size_t>(multitap_mode)][physical_port])
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
labels[logical_port] = TinyString::FromFormat("Port %u%c", physical_port + 1u, 'A' + i);
|
|
||||||
logical_port++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
labels[logical_port] = TinyString::FromFormat("Port %u", physical_port + 1u);
|
|
||||||
logical_port++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Settings::CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator)
|
void Settings::CPUOverclockPercentToFraction(u32 percent, u32* numerator, u32* denominator)
|
||||||
{
|
{
|
||||||
const u32 percent_gcd = std::gcd(percent, 100);
|
const u32 percent_gcd = std::gcd(percent, 100);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/settings_interface.h"
|
#include "common/settings_interface.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "util/audio_stream.h"
|
#include "util/audio_stream.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -246,8 +246,6 @@ struct Settings
|
||||||
std::string pcdrv_root;
|
std::string pcdrv_root;
|
||||||
bool pcdrv_enable_writes = false;
|
bool pcdrv_enable_writes = false;
|
||||||
|
|
||||||
std::array<TinyString, NUM_CONTROLLER_AND_CARD_PORTS> GeneratePortLabels() const;
|
|
||||||
|
|
||||||
LOGLEVEL log_level = DEFAULT_LOG_LEVEL;
|
LOGLEVEL log_level = DEFAULT_LOG_LEVEL;
|
||||||
std::string log_filter;
|
std::string log_filter;
|
||||||
bool log_to_console = DEFAULT_LOG_TO_CONSOLE;
|
bool log_to_console = DEFAULT_LOG_TO_CONSOLE;
|
||||||
|
|
|
@ -237,7 +237,7 @@ static bool s_discord_presence_active = false;
|
||||||
|
|
||||||
static TinyString GetTimestampStringForFileName()
|
static TinyString GetTimestampStringForFileName()
|
||||||
{
|
{
|
||||||
return TinyString::FromFmt("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(std::time(nullptr)));
|
return TinyString::from_fmt("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(std::time(nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::Internal::ProcessStartup()
|
void System::Internal::ProcessStartup()
|
||||||
|
@ -3341,25 +3341,21 @@ bool System::CheckForSBIFile(CDImage* image)
|
||||||
{
|
{
|
||||||
return Host::ConfirmMessage(
|
return Host::ConfirmMessage(
|
||||||
"Confirm Unsupported Configuration",
|
"Confirm Unsupported Configuration",
|
||||||
StringUtil::StdStringFromFormat(
|
LargeString::from_fmt(
|
||||||
TRANSLATE(
|
TRANSLATE_FS("System", "You are attempting to run a libcrypt protected game without an SBI file:\n\n{0}: "
|
||||||
"System",
|
"{1}\n\nThe game will likely not run properly.\n\nPlease check the README for "
|
||||||
"You are attempting to run a libcrypt protected game without an SBI file:\n\n%s: %s\n\nThe game will "
|
"instructions on how to add an SBI file.\n\nDo you wish to continue?"),
|
||||||
"likely not run properly.\n\nPlease check the README for instructions on how to add an SBI file.\n\nDo "
|
s_running_game_serial, s_running_game_title));
|
||||||
"you wish to continue?"),
|
|
||||||
s_running_game_serial.c_str(), s_running_game_title.c_str())
|
|
||||||
.c_str());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Host::ReportErrorAsync(
|
Host::ReportErrorAsync(
|
||||||
TRANSLATE("System", "Error"),
|
TRANSLATE("System", "Error"),
|
||||||
SmallString::FromFormat(
|
LargeString::from_fmt(
|
||||||
TRANSLATE("System",
|
TRANSLATE_FS("System", "You are attempting to run a libcrypt protected game without an SBI file:\n\n{0}: "
|
||||||
"You are attempting to run a libcrypt protected game without an SBI file:\n\n%s: %s\n\nYour dump is "
|
"{1}\n\nYour dump is incomplete, you must add the SBI file to run this game. \n\nThe "
|
||||||
"incomplete, you must add the SBI file to run this game. \n\n"
|
"name of the SBI file must match the name of the disc image."),
|
||||||
"The name of the SBI file must match the name of the disc image."),
|
s_running_game_serial, s_running_game_title));
|
||||||
s_running_game_serial.c_str(), s_running_game_title.c_str()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ void AutoUpdaterDialog::queueGetLatestRelease()
|
||||||
connect(m_network_access_mgr, &QNetworkAccessManager::finished, this, &AutoUpdaterDialog::getLatestReleaseComplete);
|
connect(m_network_access_mgr, &QNetworkAccessManager::finished, this, &AutoUpdaterDialog::getLatestReleaseComplete);
|
||||||
|
|
||||||
SmallString url_string;
|
SmallString url_string;
|
||||||
url_string.Format(LATEST_RELEASE_URL, getCurrentUpdateTag().c_str());
|
url_string.format(LATEST_RELEASE_URL, getCurrentUpdateTag().c_str());
|
||||||
|
|
||||||
QUrl url(QUrl::fromEncoded(QByteArray(url_string)));
|
QUrl url(QUrl::fromEncoded(QByteArray(url_string)));
|
||||||
QNetworkRequest request(url);
|
QNetworkRequest request(url);
|
||||||
|
|
|
@ -402,11 +402,11 @@ QString ControllerMacroEditWidget::getSummary() const
|
||||||
SmallString str;
|
SmallString str;
|
||||||
for (const Controller::ControllerBindingInfo* bi : m_binds)
|
for (const Controller::ControllerBindingInfo* bi : m_binds)
|
||||||
{
|
{
|
||||||
if (!str.IsEmpty())
|
if (!str.empty())
|
||||||
str.AppendCharacter('/');
|
str.append('/');
|
||||||
str.AppendString(bi->name);
|
str.append(bi->name);
|
||||||
}
|
}
|
||||||
return str.IsEmpty() ? tr("Not Configured") : QString::fromUtf8(str.GetCharArray(), str.GetLength());
|
return str.empty() ? tr("Not Configured") : QString::fromUtf8(str.c_str(), static_cast<int>(str.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerMacroEditWidget::onSetFrequencyClicked()
|
void ControllerMacroEditWidget::onSetFrequencyClicked()
|
||||||
|
|
|
@ -2,9 +2,13 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#include "debuggermodels.h"
|
#include "debuggermodels.h"
|
||||||
|
|
||||||
#include "core/cpu_core.h"
|
#include "core/cpu_core.h"
|
||||||
#include "core/cpu_core_private.h"
|
#include "core/cpu_core_private.h"
|
||||||
#include "core/cpu_disasm.h"
|
#include "core/cpu_disasm.h"
|
||||||
|
|
||||||
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include <QtGui/QColor>
|
#include <QtGui/QColor>
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
#include <QtGui/QPalette>
|
#include <QtGui/QPalette>
|
||||||
|
@ -21,7 +25,9 @@ DebuggerCodeModel::DebuggerCodeModel(QObject* parent /*= nullptr*/) : QAbstractT
|
||||||
m_breakpoint_pixmap = QIcon(QStringLiteral(":/icons/media-record.png")).pixmap(QSize(12, 12));
|
m_breakpoint_pixmap = QIcon(QStringLiteral(":/icons/media-record.png")).pixmap(QSize(12, 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerCodeModel::~DebuggerCodeModel() {}
|
DebuggerCodeModel::~DebuggerCodeModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int DebuggerCodeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
int DebuggerCodeModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
||||||
{
|
{
|
||||||
|
@ -92,7 +98,7 @@ QVariant DebuggerCodeModel::data(const QModelIndex& index, int role /*= Qt::Disp
|
||||||
|
|
||||||
SmallString str;
|
SmallString str;
|
||||||
CPU::DisassembleInstruction(&str, address, instruction_bits);
|
CPU::DisassembleInstruction(&str, address, instruction_bits);
|
||||||
return QString::fromUtf8(str.GetCharArray(), static_cast<int>(str.GetLength()));
|
return QString::fromUtf8(str.c_str(), static_cast<int>(str.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -107,7 +113,7 @@ QVariant DebuggerCodeModel::data(const QModelIndex& index, int role /*= Qt::Disp
|
||||||
|
|
||||||
TinyString str;
|
TinyString str;
|
||||||
CPU::DisassembleInstructionComment(&str, address, instruction_bits, &CPU::g_state.regs);
|
CPU::DisassembleInstructionComment(&str, address, instruction_bits, &CPU::g_state.regs);
|
||||||
return QString::fromUtf8(str.GetCharArray(), static_cast<int>(str.GetLength()));
|
return QString::fromUtf8(str.c_str(), static_cast<int>(str.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -287,9 +293,13 @@ void DebuggerCodeModel::setBreakpointState(VirtualMemoryAddress address, bool en
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerRegistersModel::DebuggerRegistersModel(QObject* parent /*= nullptr*/) : QAbstractListModel(parent) {}
|
DebuggerRegistersModel::DebuggerRegistersModel(QObject* parent /*= nullptr*/) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
DebuggerRegistersModel::~DebuggerRegistersModel() {}
|
DebuggerRegistersModel::~DebuggerRegistersModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int DebuggerRegistersModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
int DebuggerRegistersModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
||||||
{
|
{
|
||||||
|
@ -314,8 +324,8 @@ QVariant DebuggerRegistersModel::data(const QModelIndex& index, int role /*= Qt:
|
||||||
{
|
{
|
||||||
case 0: // address
|
case 0: // address
|
||||||
{
|
{
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
return QString::fromUtf8(CPU::g_debugger_register_list[reg_index].name);
|
return QString::fromUtf8(CPU::g_debugger_register_list[reg_index].name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -372,9 +382,13 @@ void DebuggerRegistersModel::saveCurrentValues()
|
||||||
m_old_reg_values[i] = CPU::g_state.regs.r[i];
|
m_old_reg_values[i] = CPU::g_state.regs.r[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
DebuggerStackModel::DebuggerStackModel(QObject* parent /*= nullptr*/) : QAbstractListModel(parent) {}
|
DebuggerStackModel::DebuggerStackModel(QObject* parent /*= nullptr*/) : QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
DebuggerStackModel::~DebuggerStackModel() {}
|
DebuggerStackModel::~DebuggerStackModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int DebuggerStackModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
int DebuggerStackModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -481,7 +481,7 @@ void GameListWidget::resizeTableViewColumnsToFit()
|
||||||
|
|
||||||
static TinyString getColumnVisibilitySettingsKeyName(int column)
|
static TinyString getColumnVisibilitySettingsKeyName(int column)
|
||||||
{
|
{
|
||||||
return TinyString::FromFormat("Show%s", GameListModel::getColumnName(static_cast<GameListModel::Column>(column)));
|
return TinyString::from_fmt("Show{}", GameListModel::getColumnName(static_cast<GameListModel::Column>(column)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameListWidget::loadTableViewColumnVisibilitySettings()
|
void GameListWidget::loadTableViewColumnVisibilitySettings()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#include "memorycardsettingswidget.h"
|
#include "memorycardsettingswidget.h"
|
||||||
#include "common/string_util.h"
|
|
||||||
#include "core/controller.h"
|
#include "core/controller.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "inputbindingwidgets.h"
|
#include "inputbindingwidgets.h"
|
||||||
|
@ -11,6 +11,10 @@
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
#include "settingsdialog.h"
|
#include "settingsdialog.h"
|
||||||
#include "settingwidgetbinder.h"
|
#include "settingwidgetbinder.h"
|
||||||
|
|
||||||
|
#include "common/small_string.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtWidgets/QFileDialog>
|
#include <QtWidgets/QFileDialog>
|
||||||
#include <QtWidgets/QLabel>
|
#include <QtWidgets/QLabel>
|
||||||
|
@ -168,7 +172,7 @@ void MemoryCardSettingsWidget::onBrowseMemoryCardPathClicked(int index)
|
||||||
|
|
||||||
void MemoryCardSettingsWidget::onMemoryCardPathChanged(int index)
|
void MemoryCardSettingsWidget::onMemoryCardPathChanged(int index)
|
||||||
{
|
{
|
||||||
const auto key = TinyString::FromFormat("Card%dPath", index + 1);
|
const auto key = TinyString::from_fmt("Card{}Path", index + 1);
|
||||||
std::string relative_path(
|
std::string relative_path(
|
||||||
Path::MakeRelative(m_port_ui[index].memory_card_path->text().toStdString(), EmuFolders::MemoryCards));
|
Path::MakeRelative(m_port_ui[index].memory_card_path->text().toStdString(), EmuFolders::MemoryCards));
|
||||||
m_dialog->setStringSettingValue("MemoryCards", key, relative_path.c_str());
|
m_dialog->setStringSettingValue("MemoryCards", key, relative_path.c_str());
|
||||||
|
@ -176,7 +180,7 @@ void MemoryCardSettingsWidget::onMemoryCardPathChanged(int index)
|
||||||
|
|
||||||
void MemoryCardSettingsWidget::onResetMemoryCardPathClicked(int index)
|
void MemoryCardSettingsWidget::onResetMemoryCardPathClicked(int index)
|
||||||
{
|
{
|
||||||
const auto key = TinyString::FromFormat("Card%dPath", index + 1);
|
const auto key = TinyString::from_fmt("Card{}Path", index + 1);
|
||||||
if (m_dialog->isPerGameSettings())
|
if (m_dialog->isPerGameSettings())
|
||||||
m_dialog->removeSettingValue("MemoryCards", key);
|
m_dialog->removeSettingValue("MemoryCards", key);
|
||||||
else
|
else
|
||||||
|
@ -187,7 +191,7 @@ void MemoryCardSettingsWidget::onResetMemoryCardPathClicked(int index)
|
||||||
|
|
||||||
void MemoryCardSettingsWidget::updateMemoryCardPath(int index)
|
void MemoryCardSettingsWidget::updateMemoryCardPath(int index)
|
||||||
{
|
{
|
||||||
const auto key = TinyString::FromFormat("Card%dPath", index + 1);
|
const auto key = TinyString::from_fmt("Card{}Path", index + 1);
|
||||||
std::string path(
|
std::string path(
|
||||||
m_dialog->getEffectiveStringValue("MemoryCards", key, Settings::GetDefaultSharedMemoryCardName(index).c_str()));
|
m_dialog->getEffectiveStringValue("MemoryCards", key, Settings::GetDefaultSharedMemoryCardName(index).c_str()));
|
||||||
if (!Path::IsAbsolute(path))
|
if (!Path::IsAbsolute(path))
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
|
||||||
#include <QtWidgets/QComboBox>
|
#include <QtWidgets/QComboBox>
|
||||||
#include <QtWidgets/QGroupBox>
|
#include <QtWidgets/QGroupBox>
|
||||||
#include <QtWidgets/QLineEdit>
|
#include <QtWidgets/QLineEdit>
|
||||||
|
|
|
@ -128,7 +128,7 @@ void Win32ProgressCallback::Redraw(bool force)
|
||||||
|
|
||||||
SendMessageA(m_progress_hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, m_progress_range));
|
SendMessageA(m_progress_hwnd, PBM_SETRANGE, 0, MAKELPARAM(0, m_progress_range));
|
||||||
SendMessageA(m_progress_hwnd, PBM_SETPOS, static_cast<WPARAM>(m_progress_value), 0);
|
SendMessageA(m_progress_hwnd, PBM_SETPOS, static_cast<WPARAM>(m_progress_value), 0);
|
||||||
SetWindowTextA(m_text_hwnd, m_status_text);
|
SetWindowTextA(m_text_hwnd, m_status_text.c_str());
|
||||||
RedrawWindow(m_text_hwnd, nullptr, nullptr, RDW_INVALIDATE);
|
RedrawWindow(m_text_hwnd, nullptr, nullptr, RDW_INVALIDATE);
|
||||||
PumpMessages();
|
PumpMessages();
|
||||||
}
|
}
|
||||||
|
|
|
@ -666,7 +666,7 @@ bool CDImagePBP::OpenDisc(u32 index, Error* error)
|
||||||
if (m_disc_offsets.size() > 1)
|
if (m_disc_offsets.size() > 1)
|
||||||
{
|
{
|
||||||
std::string sbi_path(Path::StripExtension(m_filename));
|
std::string sbi_path(Path::StripExtension(m_filename));
|
||||||
sbi_path += TinyString::FromFormat("_%u.sbi", index + 1);
|
sbi_path += TinyString::from_fmt("_%u.sbi", index + 1).view();
|
||||||
m_sbi.LoadSBI(sbi_path.c_str());
|
m_sbi.LoadSBI(sbi_path.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -71,10 +71,10 @@ void File::SetError(u32 line_number, Error* error, const char* format, ...)
|
||||||
std::va_list ap;
|
std::va_list ap;
|
||||||
SmallString str;
|
SmallString str;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
str.FormatVA(format, ap);
|
str.format_va(format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
Log_ErrorPrintf("Cue parse error at line %u: %s", line_number, str.GetCharArray());
|
Log_ErrorPrintf("Cue parse error at line %u: %s", line_number, str.c_str());
|
||||||
Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str));
|
Error::SetString(error, fmt::format("Cue parse error at line {}: {}", line_number, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "D3D12MemAlloc.h"
|
#include "D3D12MemAlloc.h"
|
||||||
|
|
|
@ -265,7 +265,7 @@ void GPUDevice::OpenShaderCache(const std::string_view& base_path, u32 version)
|
||||||
if (m_features.pipeline_cache)
|
if (m_features.pipeline_cache)
|
||||||
{
|
{
|
||||||
const std::string pc_filename =
|
const std::string pc_filename =
|
||||||
Path::Combine(base_path, TinyString::FromFmt("{}.bin", GetShaderCacheBaseName("pipelines")));
|
Path::Combine(base_path, TinyString::from_fmt("{}.bin", GetShaderCacheBaseName("pipelines")));
|
||||||
if (FileSystem::FileExists(pc_filename.c_str()))
|
if (FileSystem::FileExists(pc_filename.c_str()))
|
||||||
{
|
{
|
||||||
Log_InfoPrintf("Removing old pipeline cache '%s'", pc_filename.c_str());
|
Log_InfoPrintf("Removing old pipeline cache '%s'", pc_filename.c_str());
|
||||||
|
@ -284,7 +284,7 @@ void GPUDevice::OpenShaderCache(const std::string_view& base_path, u32 version)
|
||||||
if (m_features.pipeline_cache && !base_path.empty())
|
if (m_features.pipeline_cache && !base_path.empty())
|
||||||
{
|
{
|
||||||
const std::string basename = GetShaderCacheBaseName("pipelines");
|
const std::string basename = GetShaderCacheBaseName("pipelines");
|
||||||
const std::string filename = Path::Combine(base_path, TinyString::FromFmt("{}.bin", basename));
|
const std::string filename = Path::Combine(base_path, TinyString::from_fmt("{}.bin", basename));
|
||||||
if (ReadPipelineCache(filename))
|
if (ReadPipelineCache(filename))
|
||||||
s_pipeline_cache_path = std::move(filename);
|
s_pipeline_cache_path = std::move(filename);
|
||||||
else
|
else
|
||||||
|
|
|
@ -2375,12 +2375,12 @@ void ImGuiFullscreen::DrawBackgroundProgressDialogs(ImVec2& position, float spac
|
||||||
dl->AddRectFilled(pos, ImVec2(pos.x + fraction * (box_end.x - pos.x), box_end.y),
|
dl->AddRectFilled(pos, ImVec2(pos.x + fraction * (box_end.x - pos.x), box_end.y),
|
||||||
ImGui::GetColorU32(UISecondaryColor));
|
ImGui::GetColorU32(UISecondaryColor));
|
||||||
|
|
||||||
const auto text = TinyString::FromFmt("{}%", static_cast<int>(std::round(fraction * 100.0f)));
|
const auto text = TinyString::from_fmt("{}%", static_cast<int>(std::round(fraction * 100.0f)));
|
||||||
const ImVec2 text_size(ImGui::CalcTextSize(text));
|
const ImVec2 text_size(ImGui::CalcTextSize(text));
|
||||||
const ImVec2 text_pos(pos.x + ((box_end.x - pos.x) / 2.0f) - (text_size.x / 2.0f),
|
const ImVec2 text_pos(pos.x + ((box_end.x - pos.x) / 2.0f) - (text_size.x / 2.0f),
|
||||||
pos.y + ((box_end.y - pos.y) / 2.0f) - (text_size.y / 2.0f));
|
pos.y + ((box_end.y - pos.y) / 2.0f) - (text_size.y / 2.0f));
|
||||||
dl->AddText(g_medium_font, g_medium_font->FontSize, text_pos, ImGui::GetColorU32(UIPrimaryTextColor),
|
dl->AddText(g_medium_font, g_medium_font->FontSize, text_pos, ImGui::GetColorU32(UIPrimaryTextColor),
|
||||||
text.GetCharArray(), text.GetCharArray() + text.GetLength());
|
text.c_str(), text.end_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1714,9 +1714,9 @@ bool InputManager::MigrateBindings(SettingsInterface& si)
|
||||||
if (bnum >= std::size(button_mapping))
|
if (bnum >= std::size(button_mapping))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_bind.Fmt("SDL-{}/{}", cnum, button_mapping[bnum]);
|
new_bind.fmt("SDL-{}/{}", cnum, button_mapping[bnum]);
|
||||||
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
||||||
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.GetCharArray());
|
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.c_str());
|
||||||
num_changes++;
|
num_changes++;
|
||||||
}
|
}
|
||||||
else if (std::sscanf(old_bind.c_str(), "Controller%u/%cAxis%u", &cnum, &dir, &bnum) == 3)
|
else if (std::sscanf(old_bind.c_str(), "Controller%u/%cAxis%u", &cnum, &dir, &bnum) == 3)
|
||||||
|
@ -1724,16 +1724,16 @@ bool InputManager::MigrateBindings(SettingsInterface& si)
|
||||||
if (bnum >= std::size(axis_mapping))
|
if (bnum >= std::size(axis_mapping))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_bind.Fmt("SDL-{}/{}{}", cnum, dir, axis_mapping[bnum]);
|
new_bind.fmt("SDL-{}/{}{}", cnum, dir, axis_mapping[bnum]);
|
||||||
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
||||||
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.GetCharArray());
|
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.c_str());
|
||||||
num_changes++;
|
num_changes++;
|
||||||
}
|
}
|
||||||
else if (StringUtil::StartsWith(old_bind.c_str(), "Keyboard/Keypad+"))
|
else if (StringUtil::StartsWith(old_bind.c_str(), "Keyboard/Keypad+"))
|
||||||
{
|
{
|
||||||
new_bind.Fmt("Keyboard/Numpad{}", old_bind.substr(16));
|
new_bind.fmt("Keyboard/Numpad{}", old_bind.substr(16));
|
||||||
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
si.SetStringValue(new_section.c_str(), new_key, new_bind);
|
||||||
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.GetCharArray());
|
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.c_str());
|
||||||
num_changes++;
|
num_changes++;
|
||||||
}
|
}
|
||||||
else if (StringUtil::StartsWith(old_bind.c_str(), "Keyboard/"))
|
else if (StringUtil::StartsWith(old_bind.c_str(), "Keyboard/"))
|
||||||
|
@ -1764,12 +1764,12 @@ bool InputManager::MigrateBindings(SettingsInterface& si)
|
||||||
if (bnum >= std::size(axis_mapping))
|
if (bnum >= std::size(axis_mapping))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
new_bind.Fmt("SDL-{}/-{}", cnum, axis_mapping[bnum]);
|
new_bind.fmt("SDL-{}/-{}", cnum, axis_mapping[bnum]);
|
||||||
si.SetStringValue(new_section.c_str(), new_neg_key, new_bind);
|
si.SetStringValue(new_section.c_str(), new_neg_key, new_bind);
|
||||||
new_bind.Fmt("SDL-{}/+{}", cnum, axis_mapping[bnum]);
|
new_bind.fmt("SDL-{}/+{}", cnum, axis_mapping[bnum]);
|
||||||
si.SetStringValue(new_section.c_str(), new_pos_key, new_bind);
|
si.SetStringValue(new_section.c_str(), new_pos_key, new_bind);
|
||||||
|
|
||||||
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.GetCharArray());
|
Log_DevPrintf("%s -> %s", old_bind.c_str(), new_bind.c_str());
|
||||||
num_changes++;
|
num_changes++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1780,9 +1780,9 @@ bool InputManager::MigrateBindings(SettingsInterface& si)
|
||||||
unsigned cnum;
|
unsigned cnum;
|
||||||
if (std::sscanf(rumble_source.c_str(), "Controller%u", &cnum) == 1)
|
if (std::sscanf(rumble_source.c_str(), "Controller%u", &cnum) == 1)
|
||||||
{
|
{
|
||||||
new_bind.Fmt("SDL-{}/LargeMotor", cnum);
|
new_bind.fmt("SDL-{}/LargeMotor", cnum);
|
||||||
si.SetStringValue(new_section.c_str(), "LargeMotor", new_bind);
|
si.SetStringValue(new_section.c_str(), "LargeMotor", new_bind);
|
||||||
new_bind.Fmt("SDL-{}/SmallMotor", cnum);
|
new_bind.fmt("SDL-{}/SmallMotor", cnum);
|
||||||
si.SetStringValue(new_section.c_str(), "SmallMotor", new_bind);
|
si.SetStringValue(new_section.c_str(), "SmallMotor", new_bind);
|
||||||
num_changes++;
|
num_changes++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
@ -358,7 +358,7 @@ GLuint OpenGLDevice::CompileProgram(const GPUPipeline::GraphicsConfig& plconfig)
|
||||||
{
|
{
|
||||||
glBindAttribLocation(
|
glBindAttribLocation(
|
||||||
program_id, i,
|
program_id, i,
|
||||||
TinyString::FromFmt("{}{}", semantic_vars[static_cast<u8>(va.semantic.GetValue())], va.semantic_index));
|
TinyString::from_fmt("{}{}", semantic_vars[static_cast<u8>(va.semantic.GetValue())], va.semantic_index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ void OpenGLDevice::PostLinkProgram(const GPUPipeline::GraphicsConfig& plconfig,
|
||||||
const u32 num_textures = std::max<u32>(GetActiveTexturesForLayout(plconfig.layout), 1);
|
const u32 num_textures = std::max<u32>(GetActiveTexturesForLayout(plconfig.layout), 1);
|
||||||
for (u32 i = 0; i < num_textures; i++)
|
for (u32 i = 0; i < num_textures; i++)
|
||||||
{
|
{
|
||||||
location = glGetUniformLocation(program_id, TinyString::FromFmt("samp{}", i));
|
location = glGetUniformLocation(program_id, TinyString::from_fmt("samp{}", i));
|
||||||
if (location >= 0)
|
if (location >= 0)
|
||||||
glUniform1i(location, i);
|
glUniform1i(location, i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include "fmt/core.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "cocoa_tools.h"
|
#include "cocoa_tools.h"
|
||||||
|
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
#include <IOKit/pwr_mgt/IOPMLib.h>
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||||
|
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "platform_misc.h"
|
#include "platform_misc.h"
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
@ -120,20 +120,20 @@ TinyString PostProcessing::ValueToString(ShaderOption::Type type, u32 vector_siz
|
||||||
for (u32 i = 0; i < vector_size; i++)
|
for (u32 i = 0; i < vector_size; i++)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
ret.AppendCharacter(',');
|
ret.append(',');
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ShaderOption::Type::Bool:
|
case ShaderOption::Type::Bool:
|
||||||
ret.AppendString((value[i].int_value != 0) ? "true" : "false");
|
ret.append((value[i].int_value != 0) ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ShaderOption::Type::Int:
|
case ShaderOption::Type::Int:
|
||||||
ret.AppendFmtString("{}", value[i].int_value);
|
ret.append_fmt("{}", value[i].int_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ShaderOption::Type::Float:
|
case ShaderOption::Type::Float:
|
||||||
ret.AppendFmtString("{}", value[i].float_value);
|
ret.append_fmt("{}", value[i].float_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -207,7 +207,7 @@ std::vector<std::pair<std::string, std::string>> PostProcessing::GetAvailableSha
|
||||||
|
|
||||||
TinyString PostProcessing::GetStageConfigSection(u32 index)
|
TinyString PostProcessing::GetStageConfigSection(u32 index)
|
||||||
{
|
{
|
||||||
return TinyString::FromFmt("PostProcessing/Stage{}", index + 1);
|
return TinyString::from_fmt("PostProcessing/Stage{}", index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PostProcessing::CopyStageConfig(SettingsInterface& si, u32 old_index, u32 new_index)
|
void PostProcessing::CopyStageConfig(SettingsInterface& si, u32 old_index, u32 new_index)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "state_wrapper.h"
|
#include "state_wrapper.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
Log_SetChannel(StateWrapper);
|
Log_SetChannel(StateWrapper);
|
||||||
|
@ -67,14 +67,14 @@ void StateWrapper::Do(std::string* value_ptr)
|
||||||
value_ptr->resize(std::strlen(&(*value_ptr)[0]));
|
value_ptr->resize(std::strlen(&(*value_ptr)[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateWrapper::Do(String* value_ptr)
|
void StateWrapper::Do(SmallStringBase* value_ptr)
|
||||||
{
|
{
|
||||||
u32 length = static_cast<u32>(value_ptr->GetLength());
|
u32 length = static_cast<u32>(value_ptr->length());
|
||||||
Do(&length);
|
Do(&length);
|
||||||
if (m_mode == Mode::Read)
|
if (m_mode == Mode::Read)
|
||||||
value_ptr->Resize(length);
|
value_ptr->resize(length);
|
||||||
DoBytes(value_ptr->GetWriteableCharArray(), length);
|
DoBytes(value_ptr->data(), length);
|
||||||
value_ptr->UpdateSize();
|
value_ptr->update_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StateWrapper::DoMarker(const char* marker)
|
bool StateWrapper::DoMarker(const char* marker)
|
||||||
|
@ -84,11 +84,11 @@ bool StateWrapper::DoMarker(const char* marker)
|
||||||
if (m_error)
|
if (m_error)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_mode == Mode::Write || file_value.Compare(marker))
|
if (m_mode == Mode::Write || file_value.equals(marker))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Log_ErrorPrintf("Marker mismatch at offset %" PRIu64 ": found '%s' expected '%s'", m_stream->GetPosition(),
|
Log_ErrorPrintf("Marker mismatch at offset %" PRIu64 ": found '%s' expected '%s'", m_stream->GetPosition(),
|
||||||
file_value.GetCharArray(), marker);
|
file_value.c_str(), marker);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class String;
|
class SmallStringBase;
|
||||||
|
|
||||||
class StateWrapper
|
class StateWrapper
|
||||||
{
|
{
|
||||||
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
void Do(bool* value_ptr);
|
void Do(bool* value_ptr);
|
||||||
void Do(std::string* value_ptr);
|
void Do(std::string* value_ptr);
|
||||||
void Do(String* value_ptr);
|
void Do(SmallStringBase* value_ptr);
|
||||||
|
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
void Do(std::array<T, N>* data)
|
void Do(std::array<T, N>* data)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/path.h"
|
#include "common/path.h"
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string.h"
|
#include "common/small_string.h"
|
||||||
|
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
|
|
||||||
|
@ -662,7 +662,7 @@ bool VulkanDevice::CreateCommandBuffers()
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
|
LOG_VULKAN_ERROR(res, "vkCreateCommandPool failed: ");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vulkan::SetObjectName(m_device, resources.command_pool, TinyString::FromFmt("Frame Command Pool {}", frame_index));
|
Vulkan::SetObjectName(m_device, resources.command_pool, TinyString::from_fmt("Frame Command Pool {}", frame_index));
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr,
|
VkCommandBufferAllocateInfo buffer_info = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr,
|
||||||
resources.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
resources.command_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
@ -677,7 +677,7 @@ bool VulkanDevice::CreateCommandBuffers()
|
||||||
for (u32 i = 0; i < resources.command_buffers.size(); i++)
|
for (u32 i = 0; i < resources.command_buffers.size(); i++)
|
||||||
{
|
{
|
||||||
Vulkan::SetObjectName(m_device, resources.command_buffers[i],
|
Vulkan::SetObjectName(m_device, resources.command_buffers[i],
|
||||||
TinyString::FromFmt("Frame {} {}Command Buffer", frame_index, (i == 0) ? "Init" : ""));
|
TinyString::from_fmt("Frame {} {}Command Buffer", frame_index, (i == 0) ? "Init" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT};
|
VkFenceCreateInfo fence_info = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT};
|
||||||
|
@ -688,7 +688,7 @@ bool VulkanDevice::CreateCommandBuffers()
|
||||||
LOG_VULKAN_ERROR(res, "vkCreateFence failed: ");
|
LOG_VULKAN_ERROR(res, "vkCreateFence failed: ");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vulkan::SetObjectName(m_device, resources.fence, TinyString::FromFmt("Frame Fence {}", frame_index));
|
Vulkan::SetObjectName(m_device, resources.fence, TinyString::from_fmt("Frame Fence {}", frame_index));
|
||||||
|
|
||||||
if (!m_optional_extensions.vk_khr_push_descriptor)
|
if (!m_optional_extensions.vk_khr_push_descriptor)
|
||||||
{
|
{
|
||||||
|
@ -707,7 +707,7 @@ bool VulkanDevice::CreateCommandBuffers()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vulkan::SetObjectName(m_device, resources.descriptor_pool,
|
Vulkan::SetObjectName(m_device, resources.descriptor_pool,
|
||||||
TinyString::FromFmt("Frame Descriptor Pool {}", frame_index));
|
TinyString::from_fmt("Frame Descriptor Pool {}", frame_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
++frame_index;
|
++frame_index;
|
||||||
|
|
Loading…
Reference in a new issue