Cemu/src/Common/CafeString.h
Exzap 4fa0df6dcf
Some checks failed
Build check / build (push) Has been cancelled
Generate translation template / generate-pot (push) Has been cancelled
nn_boss: Reimplementation
This is a full rewrite of our nn_boss (SpotPass) implementation. The previous code was based on a lot of incorrect guesswork so rather than updating that it made more sense to redo it all.

In short what changed:
- More API implemented than before, but nn_boss is very complex so we are still missing stuff (e.g. PlayReports and Task scheduling)
- Avoids redownloading nbdl files if they are already present locally (matches IOSU behavior)
- The API should be more robust in general and file hashes are now verified
- Emulated IOSU interface is compatible with nn_boss.rpl
- Added an UI option to clear the SpotPass cache
2025-10-30 16:24:09 +01:00

129 lines
2.2 KiB
C++

#pragma once
#include "betype.h"
#include "util/helpers/StringHelpers.h"
/* Helper classes to represent CafeOS strings in emulated memory */
template <size_t N>
class CafeString // fixed buffer size, null-terminated, PPC char
{
public:
constexpr static size_t Size()
{
return N;
}
// checks whether the string and a null terminator can fit into the buffer
bool CanHoldString(std::string_view sv) const
{
return sv.size() < N;
}
bool assign(std::string_view sv)
{
if (sv.size() >= N)
{
memcpy(data, sv.data(), N-1);
data[N-1] = '\0';
return false;
}
memcpy(data, sv.data(), sv.size());
data[sv.size()] = '\0';
return true;
}
void Copy(CafeString<N>& other)
{
memcpy(data, other.data, N);
}
bool empty() const
{
return data[0] == '\0';
}
const char* c_str() const
{
return (const char*)data;
}
void ClearAllBytes()
{
memset(data, 0, N);
}
auto operator<=>(const CafeString<N>& other) const
{
for (size_t i = 0; i < N; i++)
{
if (data[i] != other.data[i])
return data[i] <=> other.data[i];
if (data[i] == '\0')
return std::strong_ordering::equal;
}
return std::strong_ordering::equal;
}
bool operator==(const CafeString<N>& other) const
{
for (size_t i = 0; i < N; i++)
{
if (data[i] != other.data[i])
return false;
if (data[i] == '\0')
return true;
}
return true;
}
uint8be data[N];
};
template <size_t N>
class CafeWideString // fixed buffer size, null-terminated, PPC wchar_t (16bit big-endian)
{
public:
bool assign(const uint16be* input)
{
size_t i = 0;
while(input[i])
{
if(i >= N-1)
{
data[N-1] = 0;
return false;
}
data[i] = input[i];
i++;
}
data[i] = 0;
return true;
}
bool assignFromUTF8(std::string_view sv)
{
std::vector<uint16be> beStr = StringHelpers::FromUtf8(sv);
if(beStr.size() > N-1)
{
memcpy(data, beStr.data(), (N-1)*sizeof(uint16be));
data[N-1] = 0;
return false;
}
memcpy(data, beStr.data(), beStr.size()*sizeof(uint16be));
data[beStr.size()] = '\0';
return true;
}
uint16be data[N];
};
namespace CafeStringHelpers
{
static uint32 Length(const uint16be* input, uint32 maxLength)
{
uint32 i = 0;
while(input[i] && i < maxLength)
i++;
return i;
}
};