Fix save loading, rewrite Loadout classes to use CInputStream

This commit is contained in:
Phillip Stephens 2022-02-27 19:33:48 -08:00
parent aa1d6006ed
commit 80362a9483
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
9 changed files with 144 additions and 50 deletions

View File

@ -137,6 +137,7 @@ set(RUNTIME_SOURCES_B
GCNTypes.hpp GCNTypes.hpp
CTextureCache.hpp CTextureCache.cpp CTextureCache.hpp CTextureCache.cpp
CMayaSpline.hpp CMayaSpline.cpp CMayaSpline.hpp CMayaSpline.cpp
ImGuiPlayerLoadouts.hpp ImGuiPlayerLoadouts.cpp
${PLAT_SRCS}) ${PLAT_SRCS})
function(add_runtime_common_library name) function(add_runtime_common_library name)

View File

@ -263,7 +263,7 @@ static void RenderEntityColumns(const ImGuiEntityEntry& entry) {
} }
void ImGuiConsole::ShowInspectWindow(bool* isOpen) { void ImGuiConsole::ShowInspectWindow(bool* isOpen) {
float initialWindowSize = 400.f * ImGui::GetIO().DisplayFramebufferScale.x; float initialWindowSize = 400.f * aurora::get_window_size().scale;
ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize * 1.5f}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize * 1.5f}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Inspect", isOpen)) { if (ImGui::Begin("Inspect", isOpen)) {
@ -383,7 +383,7 @@ bool ImGuiConsole::ShowEntityInfoWindow(TUniqueId uid) {
void ImGuiConsole::ShowConsoleVariablesWindow() { void ImGuiConsole::ShowConsoleVariablesWindow() {
// For some reason the window shows up tiny without this // For some reason the window shows up tiny without this
float initialWindowSize = 350.f * ImGui::GetIO().DisplayFramebufferScale.x; float initialWindowSize = 350.f * aurora::get_window_size().scale;
ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Console Variables", &m_showConsoleVariablesWindow)) { if (ImGui::Begin("Console Variables", &m_showConsoleVariablesWindow)) {
if (ImGui::Button("Clear")) { if (ImGui::Button("Clear")) {
@ -633,7 +633,7 @@ std::optional<std::string> ImGuiConsole::ShowAboutWindow(bool canClose, std::str
flags |= ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove; flags |= ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove;
} }
if (ImGui::Begin("About", open, flags)) { if (ImGui::Begin("About", open, flags)) {
float iconSize = 128.f * ImGui::GetIO().DisplayFramebufferScale.x; float iconSize = 128.f * aurora::get_window_size().scale;
ImGui::SameLine(ImGui::GetWindowSize().x / 2 - iconSize + (iconSize / 2)); ImGui::SameLine(ImGui::GetWindowSize().x / 2 - iconSize + (iconSize / 2));
ImGui::Image(ImGuiEngine::metaforceIcon, ImVec2{iconSize, iconSize}); ImGui::Image(ImGuiEngine::metaforceIcon, ImVec2{iconSize, iconSize});
ImGui::PushFont(ImGuiEngine::fontLarge); ImGui::PushFont(ImGuiEngine::fontLarge);
@ -942,7 +942,7 @@ void ImGuiConsole::ShowInputViewer() {
} }
ImGui::SetNextWindowBgAlpha(0.65f); ImGui::SetNextWindowBgAlpha(0.65f);
if (ImGui::Begin("Input Overlay", nullptr, windowFlags)) { if (ImGui::Begin("Input Overlay", nullptr, windowFlags)) {
float scale = ImGui::GetIO().DisplayFramebufferScale.x; float scale = aurora::get_window_size().scale;
if (!m_controllerName.empty()) { if (!m_controllerName.empty()) {
TextCenter(m_controllerName); TextCenter(m_controllerName);
ImGui::Separator(); ImGui::Separator();
@ -1508,7 +1508,7 @@ void ImGuiConsole::ShowItemsWindow() {
void ImGuiConsole::ShowLayersWindow() { void ImGuiConsole::ShowLayersWindow() {
// For some reason the window shows up tiny without this // For some reason the window shows up tiny without this
float initialWindowSize = 350.f * ImGui::GetIO().DisplayFramebufferScale.x; float initialWindowSize = 350.f * aurora::get_window_size().scale;
ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Layers", &m_showLayersWindow)) { if (ImGui::Begin("Layers", &m_showLayersWindow)) {

View File

@ -0,0 +1,43 @@
#include "Runtime/ImGuiPlayerLoadouts.hpp"
#include "Runtime/Streams/ContainerReaders.hpp"
#include "Runtime/Streams/ContainerWriters.hpp"
#include <logvisor/logvisor.hpp>
#include "magic_enum.hpp"
namespace metaforce {
namespace {
logvisor::Module Log("metaforce::ImGuiPlayerLoadouts");
constexpr u32 CurrentVersion = 1;
} // namespace
ImGuiPlayerLoadouts::Item::Item(CInputStream& in)
: type(magic_enum::enum_cast<CPlayerState::EItemType>(in.Get<std::string>()).value()), amount(in.ReadLong()) {}
void ImGuiPlayerLoadouts::Item::PutTo(COutputStream& out) const {
out.Put(magic_enum::enum_name<CPlayerState::EItemType>(type));
out.Put(amount);
}
ImGuiPlayerLoadouts::LoadOut::LoadOut(CInputStream& in) : name(in.Get<std::string>()) { read_vector(items, in); }
void ImGuiPlayerLoadouts::LoadOut::PutTo(COutputStream& out) const {
out.Put(name);
write_vector(items, out);
}
ImGuiPlayerLoadouts::ImGuiPlayerLoadouts(CInputStream& in) {
FourCC magic;
in.Get(reinterpret_cast<u8*>(&magic), 4);
auto version = in.ReadLong();
if (magic != FOURCC('LOAD') && version != CurrentVersion) {
Log.report(logvisor::Error, FMT_STRING("Incorrect loadout version, expected {} got {}"), CurrentVersion, version);
return;
}
read_vector(loadouts, in);
}
void ImGuiPlayerLoadouts::PutTo(COutputStream& out) const {
auto magic = FOURCC('LOAD');
out.Put(reinterpret_cast<const u8*>(&magic), 4);
out.Put(CurrentVersion);
write_vector(loadouts, out);
}
} // namespace metaforce

View File

@ -1,23 +1,27 @@
#pragma once #pragma once
#include <athena/DNA.hpp> #include "Runtime/CPlayerState.hpp"
#include <athena/DNAYaml.hpp>
namespace metaforce { namespace metaforce {
struct ImGuiPlayerLoadouts : athena::io::DNA<athena::Endian::Big> { struct ImGuiPlayerLoadouts {
AT_DECL_DNA_YAML struct Item {
struct Item : athena::io::DNA<athena::Endian::Big> { CPlayerState::EItemType type = CPlayerState::EItemType::Invalid;
AT_DECL_DNA_YAML u32 amount = 0;
String<-1> type; Item() = default;
Value<u32> amount; explicit Item(CInputStream& in);
void PutTo(COutputStream& out) const;
}; };
struct LoadOut : athena::io::DNA<athena::Endian::Big> { struct LoadOut{
AT_DECL_DNA_YAML std::string name;
String<-1> name; std::vector<Item> items;
Value<u32> itemCount; LoadOut() = default;
Vector<Item, AT_DNA_COUNT(itemCount)> items; explicit LoadOut(CInputStream& in);
void PutTo(COutputStream& out) const;
}; };
Value<u32> loadoutCount; std::vector<LoadOut> loadouts;
Vector<LoadOut, AT_DNA_COUNT(loadoutCount)> loadouts;
ImGuiPlayerLoadouts() = default;
explicit ImGuiPlayerLoadouts(CInputStream& in);
void PutTo(COutputStream& out) const;
}; };
} // namespace metaforce } // namespace metaforce

View File

@ -89,32 +89,36 @@ u32 CInputStream::ReadBytes(void* dest, u32 len) {
return curReadLen; return curReadLen;
} }
u32 CInputStream::ReadBits(u32 bitCount) {
u32 ret = x20_bitOffset;
if (ret < bitCount) {
const u32 shiftAmt = bitCount - x20_bitOffset;
const u32 mask = ret == 32 ? -1 : (1 << x20_bitOffset) - 1;
u32 uVar2 = x1c_bitWord; u32 CInputStream::ReadBits(u32 bitCount) {
x20_bitOffset = 0; u32 ret = 0;
u32 len = min_containing_bytes(shiftAmt); const s32 shiftAmt = x20_bitOffset - s32(bitCount);
Get(reinterpret_cast<u8*>(&x1c_bitWord), len); if (shiftAmt < 0) {
/* OR in remaining bits of cached value */
u32 mask = bitCount == 32 ? UINT32_MAX : ((1U << bitCount) - 1);
ret |= (x1c_bitWord << u32(-shiftAmt)) & mask;
/* Load in exact number of bytes remaining */
auto loadDiv = std::div(-shiftAmt, 8);
if (loadDiv.rem != 0) {
++loadDiv.quot;
}
Get(reinterpret_cast<u8*>(&x1c_bitWord) + 4 - loadDiv.quot, loadDiv.quot);
#if METAFORCE_TARGET_BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ #if METAFORCE_TARGET_BYTE_ORDER == __ORDER_LITTLE_ENDIAN__
x1c_bitWord = CBasics::SwapBytes(x1c_bitWord); x1c_bitWord = CBasics::SwapBytes(x1c_bitWord);
#endif #endif
/* New bit offset */
const u32 retMask = shiftAmt == 32 ? -1 : (1 << shiftAmt) - 1; x20_bitOffset = loadDiv.quot * 8 + shiftAmt;
const u32 tmpOffset = x20_bitOffset; /* OR in next bits */
x20_bitOffset = len * 8; mask = (1U << u32(-shiftAmt)) - 1;
ret = ((mask & uVar2) >> (32 - ret) << shiftAmt) | (retMask & (x1c_bitWord >> (32 - shiftAmt))) << tmpOffset; ret |= (x1c_bitWord >> x20_bitOffset) & mask;
x20_bitOffset -= shiftAmt;
x1c_bitWord <<= shiftAmt;
} else { } else {
/* OR in bits of cached value */
const u32 mask = bitCount == 32 ? UINT32_MAX : ((1U << bitCount) - 1);
ret |= (x1c_bitWord >> u32(shiftAmt)) & mask;
/* New bit offset */
x20_bitOffset -= bitCount; x20_bitOffset -= bitCount;
ret = bitCount == 32 ? -1 : (1 << bitCount) - 1;
ret &= x1c_bitWord >> (32 - bitCount);
x1c_bitWord <<= bitCount;
} }
return ret; return ret;
} }

View File

@ -78,27 +78,27 @@ void COutputStream::Put(const u8* ptr, u32 len) {
} }
void COutputStream::WriteBits(u32 val, u32 bitCount) { void COutputStream::WriteBits(u32 val, u32 bitCount) {
const u32 bitOffset = x18_shiftRegisterOffset; const s32 shiftAmt = x18_shiftRegisterOffset - s32(bitCount);
if (x18_shiftRegisterOffset < bitCount) { if (shiftAmt < 0) {
/* OR remaining bits to cached value */ /* OR remaining bits to cached value */
const u32 shiftAmt = (bitCount - x18_shiftRegisterOffset); const u32 mask = (1U << x18_shiftRegisterOffset) - 1;
const u32 mask = bitOffset == 32 ? -1 : (1 << bitOffset) - 1; x14_shiftRegister |= (val >> u32(-shiftAmt)) & mask;
/* Write out 32-bits */ /* Write out 32-bits */
x14_shiftRegister |= (val >> shiftAmt) & mask;
x18_shiftRegisterOffset = 0;
FlushShiftRegister(); FlushShiftRegister();
/* Cache remaining bits */ /* Cache remaining bits */
x14_shiftRegister = (val & (shiftAmt == 32 ? -1 : (1 << shiftAmt) - 1)) << (32 - shiftAmt); x18_shiftRegisterOffset = 0x20 + shiftAmt;
x18_shiftRegisterOffset -= shiftAmt; x14_shiftRegister = val << x18_shiftRegisterOffset;
} else { } else {
/* OR bits to cached value */ /* OR bits to cached value */
const u32 mask = bitOffset == 0x20 ? -1 : (1 << bitOffset) - 1; const u32 mask = bitCount == 32 ? UINT32_MAX : ((1U << bitCount) - 1);
x14_shiftRegister |= (val & mask) << (bitOffset - bitCount); x14_shiftRegister |= (val & mask) << u32(shiftAmt);
/* New bit offset */ /* New bit offset */
x18_shiftRegisterOffset -= bitCount; x18_shiftRegisterOffset -= bitCount;
} }
} }
void COutputStream::WriteChar(u8 c) { void COutputStream::WriteChar(u8 c) {
@ -199,6 +199,14 @@ void coutput_stream_helper(const std::string& t, COutputStream& out) {
} }
} }
template <>
void coutput_stream_helper(const std::string_view& t, COutputStream& out) {
for (size_t i = 0; i < t.size() + 1; ++i) {
out.FlushShiftRegister();
out.Put(t[i]);
}
}
u32 COutputStream::GetBitCount(u32 val) { u32 COutputStream::GetBitCount(u32 val) {
int bits = 0; int bits = 0;
for (; val != 0; val >>= 1) { for (; val != 0; val >>= 1) {

View File

@ -86,4 +86,6 @@ template <>
void coutput_stream_helper(const double& t, COutputStream& out); void coutput_stream_helper(const double& t, COutputStream& out);
template <> template <>
void coutput_stream_helper(const std::string& t, COutputStream& out); void coutput_stream_helper(const std::string& t, COutputStream& out);
template <>
void coutput_stream_helper(const std::string_view& t, COutputStream& out);
} // namespace metaforce } // namespace metaforce

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#include "Runtime/rstl.hpp"
#include "Runtime/Streams/CInputStream.hpp" #include "Runtime/Streams/CInputStream.hpp"
#include "Runtime/rstl.hpp"
#include <vector>
namespace metaforce { namespace metaforce {
template <class T, size_t N> template <class T, size_t N>
void read_reserved_vector(rstl::reserved_vector<T, N>& v, CInputStream& in) { void read_reserved_vector(rstl::reserved_vector<T, N>& v, CInputStream& in) {
@ -11,4 +12,13 @@ void read_reserved_vector(rstl::reserved_vector<T, N>& v, CInputStream& in) {
v[i] = in.Get<T>(); v[i] = in.Get<T>();
} }
} }
template <class T>
void read_vector(std::vector<T>& v, CInputStream& in) {
u32 count = in.ReadLong();
v.reserve(count);
for (u32 i = 0; i < count; ++i) {
v.emplace_back(in.Get<T>());
}
}
} // namespace metaforce } // namespace metaforce

View File

@ -0,0 +1,22 @@
#pragma once
#include "Runtime/Streams/COutputStream.hpp"
#include "Runtime/rstl.hpp"
#include <vector>
namespace metaforce {
template <class T, size_t N>
void write_reserved_vector(const rstl::reserved_vector<T, N>& v, COutputStream& out) {
out.Put(v.size());
for (const auto& t : v) {
out.Put(t);
}
}
template <class T>
void write_vector(const std::vector<T>& v, COutputStream& out) {
out.Put(v.size());
for (const auto& t : v) {
out.Put(t);
}
}
} // namespace metaforce