global: Use std::optional instead of boost::optional (#1578)
* get rid of boost::optional * Remove optional references * Use std::reference_wrapper for optional references * Fix clang format * Fix clang format part 2 * Adressed feedback * Fix clang format and MacOS build
This commit is contained in:
parent
adf26ae668
commit
7a5eda5914
|
@ -185,7 +185,7 @@ struct System::Impl {
|
||||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||||
return ResultStatus::ErrorGetLoader;
|
return ResultStatus::ErrorGetLoader;
|
||||||
}
|
}
|
||||||
std::pair<boost::optional<u32>, Loader::ResultStatus> system_mode =
|
std::pair<std::optional<u32>, Loader::ResultStatus> system_mode =
|
||||||
app_loader->LoadKernelSystemMode();
|
app_loader->LoadKernelSystemMode();
|
||||||
|
|
||||||
if (system_mode.second != Loader::ResultStatus::Success) {
|
if (system_mode.second != Loader::ResultStatus::Success) {
|
||||||
|
|
|
@ -141,28 +141,28 @@ Key128 DeriveKeyblobMACKey(const Key128& keyblob_key, const Key128& mac_source)
|
||||||
return mac_key;
|
return mac_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<Key128> DeriveSDSeed() {
|
std::optional<Key128> DeriveSDSeed() {
|
||||||
const FileUtil::IOFile save_43(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
|
const FileUtil::IOFile save_43(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) +
|
||||||
"/system/save/8000000000000043",
|
"/system/save/8000000000000043",
|
||||||
"rb+");
|
"rb+");
|
||||||
if (!save_43.IsOpen())
|
if (!save_43.IsOpen())
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
const FileUtil::IOFile sd_private(
|
const FileUtil::IOFile sd_private(
|
||||||
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
|
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir) + "/Nintendo/Contents/private", "rb+");
|
||||||
if (!sd_private.IsOpen())
|
if (!sd_private.IsOpen())
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
std::array<u8, 0x10> private_seed{};
|
std::array<u8, 0x10> private_seed{};
|
||||||
if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
|
if (sd_private.ReadBytes(private_seed.data(), private_seed.size()) != private_seed.size()) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, 0x10> buffer{};
|
std::array<u8, 0x10> buffer{};
|
||||||
std::size_t offset = 0;
|
std::size_t offset = 0;
|
||||||
for (; offset + 0x10 < save_43.GetSize(); ++offset) {
|
for (; offset + 0x10 < save_43.GetSize(); ++offset) {
|
||||||
if (!save_43.Seek(offset, SEEK_SET)) {
|
if (!save_43.Seek(offset, SEEK_SET)) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
save_43.ReadBytes(buffer.data(), buffer.size());
|
save_43.ReadBytes(buffer.data(), buffer.size());
|
||||||
|
@ -172,12 +172,12 @@ boost::optional<Key128> DeriveSDSeed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
|
if (!save_43.Seek(offset + 0x10, SEEK_SET)) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Key128 seed{};
|
Key128 seed{};
|
||||||
if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
|
if (save_43.ReadBytes(seed.data(), seed.size()) != seed.size()) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
@ -291,26 +291,26 @@ static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t size>
|
template <size_t size>
|
||||||
static boost::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
|
static std::optional<u64> FindTicketOffset(const std::array<u8, size>& data) {
|
||||||
u64 offset = 0;
|
u64 offset = 0;
|
||||||
for (size_t i = 0x20; i < data.size() - 0x10; ++i) {
|
for (size_t i = 0x20; i < data.size() - 0x10; ++i) {
|
||||||
if (data[i] == 0x1) {
|
if (data[i] == 0x1) {
|
||||||
offset = i + 1;
|
offset = i + 1;
|
||||||
break;
|
break;
|
||||||
} else if (data[i] != 0x0) {
|
} else if (data[i] != 0x0) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
|
std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
|
||||||
const RSAKeyPair<2048>& key) {
|
const RSAKeyPair<2048>& key) {
|
||||||
u32 cert_authority;
|
u32 cert_authority;
|
||||||
std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority));
|
std::memcpy(&cert_authority, ticket.data() + 0x140, sizeof(cert_authority));
|
||||||
if (cert_authority == 0)
|
if (cert_authority == 0)
|
||||||
return boost::none;
|
return {};
|
||||||
if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) {
|
if (cert_authority != Common::MakeMagic('R', 'o', 'o', 't')) {
|
||||||
LOG_INFO(Crypto,
|
LOG_INFO(Crypto,
|
||||||
"Attempting to parse ticket with non-standard certificate authority {:08X}.",
|
"Attempting to parse ticket with non-standard certificate authority {:08X}.",
|
||||||
|
@ -321,7 +321,7 @@ boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
|
||||||
std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
|
std::memcpy(rights_id.data(), ticket.data() + 0x2A0, sizeof(Key128));
|
||||||
|
|
||||||
if (rights_id == Key128{})
|
if (rights_id == Key128{})
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
Key128 key_temp{};
|
Key128 key_temp{};
|
||||||
|
|
||||||
|
@ -356,17 +356,17 @@ boost::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
|
||||||
std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size());
|
std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size());
|
||||||
|
|
||||||
if (m_0 != 0)
|
if (m_0 != 0)
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
m_1 = m_1 ^ MGF1<0x20>(m_2);
|
m_1 = m_1 ^ MGF1<0x20>(m_2);
|
||||||
m_2 = m_2 ^ MGF1<0xDF>(m_1);
|
m_2 = m_2 ^ MGF1<0xDF>(m_1);
|
||||||
|
|
||||||
const auto offset = FindTicketOffset(m_2);
|
const auto offset = FindTicketOffset(m_2);
|
||||||
if (offset == boost::none)
|
if (!offset)
|
||||||
return boost::none;
|
return {};
|
||||||
ASSERT(offset.get() > 0);
|
ASSERT(*offset > 0);
|
||||||
|
|
||||||
std::memcpy(key_temp.data(), m_2.data() + offset.get(), key_temp.size());
|
std::memcpy(key_temp.data(), m_2.data() + *offset, key_temp.size());
|
||||||
|
|
||||||
return std::make_pair(rights_id, key_temp);
|
return std::make_pair(rights_id, key_temp);
|
||||||
}
|
}
|
||||||
|
@ -661,8 +661,8 @@ void KeyManager::DeriveSDSeedLazy() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto res = DeriveSDSeed();
|
const auto res = DeriveSDSeed();
|
||||||
if (res != boost::none)
|
if (res)
|
||||||
SetKey(S128KeyType::SDSeed, res.get());
|
SetKey(S128KeyType::SDSeed, *res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
|
static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
|
||||||
|
@ -889,9 +889,9 @@ void KeyManager::DeriveETicket(PartitionDataManager& data) {
|
||||||
|
|
||||||
for (const auto& raw : res) {
|
for (const auto& raw : res) {
|
||||||
const auto pair = ParseTicket(raw, rsa_key);
|
const auto pair = ParseTicket(raw, rsa_key);
|
||||||
if (pair == boost::none)
|
if (!pair)
|
||||||
continue;
|
continue;
|
||||||
const auto& [rid, key] = pair.value();
|
const auto& [rid, key] = *pair;
|
||||||
u128 rights_id;
|
u128 rights_id;
|
||||||
std::memcpy(rights_id.data(), rid.data(), rid.size());
|
std::memcpy(rights_id.data(), rid.data(), rid.size());
|
||||||
SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
SetKey(S128KeyType::Titlekey, key, rights_id[1], rights_id[0]);
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <boost/container/flat_map.hpp>
|
#include <boost/container/flat_map.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/crypto/partition_data_manager.h"
|
#include "core/crypto/partition_data_manager.h"
|
||||||
|
@ -191,14 +192,14 @@ Key128 DeriveMasterKey(const std::array<u8, 0x90>& keyblob, const Key128& master
|
||||||
std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblob,
|
std::array<u8, 0x90> DecryptKeyblob(const std::array<u8, 0xB0>& encrypted_keyblob,
|
||||||
const Key128& key);
|
const Key128& key);
|
||||||
|
|
||||||
boost::optional<Key128> DeriveSDSeed();
|
std::optional<Key128> DeriveSDSeed();
|
||||||
Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys);
|
Loader::ResultStatus DeriveSDKeys(std::array<Key256, 2>& sd_keys, KeyManager& keys);
|
||||||
|
|
||||||
std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save);
|
std::vector<TicketRaw> GetTicketblob(const FileUtil::IOFile& ticket_save);
|
||||||
|
|
||||||
// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset
|
// Returns a pair of {rights_id, titlekey}. Fails if the ticket has no certificate authority (offset
|
||||||
// 0x140-0x144 is zero)
|
// 0x140-0x144 is zero)
|
||||||
boost::optional<std::pair<Key128, Key128>> ParseTicket(
|
std::optional<std::pair<Key128, Key128>> ParseTicket(const TicketRaw& ticket,
|
||||||
const TicketRaw& ticket, const RSAKeyPair<2048>& eticket_extended_key);
|
const RSAKeyPair<2048>& eticket_extended_key);
|
||||||
|
|
||||||
} // namespace Core::Crypto
|
} // namespace Core::Crypto
|
||||||
|
|
|
@ -4,10 +4,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/crypto/aes_util.h"
|
#include "core/crypto/aes_util.h"
|
||||||
#include "core/crypto/ctr_encryption_layer.h"
|
#include "core/crypto/ctr_encryption_layer.h"
|
||||||
|
@ -306,18 +305,18 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
|
||||||
subsection_buckets.back().entries.push_back({section.bktr.relocation.offset, {0}, ctr_low});
|
subsection_buckets.back().entries.push_back({section.bktr.relocation.offset, {0}, ctr_low});
|
||||||
subsection_buckets.back().entries.push_back({size, {0}, 0});
|
subsection_buckets.back().entries.push_back({size, {0}, 0});
|
||||||
|
|
||||||
boost::optional<Core::Crypto::Key128> key = boost::none;
|
std::optional<Core::Crypto::Key128> key = {};
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
if (has_rights_id) {
|
if (has_rights_id) {
|
||||||
status = Loader::ResultStatus::Success;
|
status = Loader::ResultStatus::Success;
|
||||||
key = GetTitlekey();
|
key = GetTitlekey();
|
||||||
if (key == boost::none) {
|
if (!key) {
|
||||||
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
key = GetKeyAreaKey(NCASectionCryptoType::BKTR);
|
key = GetKeyAreaKey(NCASectionCryptoType::BKTR);
|
||||||
if (key == boost::none) {
|
if (!key) {
|
||||||
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
|
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -332,7 +331,7 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
|
||||||
auto bktr = std::make_shared<BKTR>(
|
auto bktr = std::make_shared<BKTR>(
|
||||||
bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
|
bktr_base_romfs, std::make_shared<OffsetVfsFile>(file, romfs_size, base_offset),
|
||||||
relocation_block, relocation_buckets, subsection_block, subsection_buckets, encrypted,
|
relocation_block, relocation_buckets, subsection_block, subsection_buckets, encrypted,
|
||||||
encrypted ? key.get() : Core::Crypto::Key128{}, base_offset, bktr_base_ivfc_offset,
|
encrypted ? *key : Core::Crypto::Key128{}, base_offset, bktr_base_ivfc_offset,
|
||||||
section.raw.section_ctr);
|
section.raw.section_ctr);
|
||||||
|
|
||||||
// BKTR applies to entire IVFC, so make an offset version to level 6
|
// BKTR applies to entire IVFC, so make an offset version to level 6
|
||||||
|
@ -388,11 +387,11 @@ u8 NCA::GetCryptoRevision() const {
|
||||||
return master_key_id;
|
return master_key_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
|
std::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type) const {
|
||||||
const auto master_key_id = GetCryptoRevision();
|
const auto master_key_id = GetCryptoRevision();
|
||||||
|
|
||||||
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index))
|
if (!keys.HasKey(Core::Crypto::S128KeyType::KeyArea, master_key_id, header.key_index))
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
std::vector<u8> key_area(header.key_area.begin(), header.key_area.end());
|
std::vector<u8> key_area(header.key_area.begin(), header.key_area.end());
|
||||||
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
|
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
|
||||||
|
@ -416,25 +415,25 @@ boost::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType ty
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
|
std::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
|
||||||
const auto master_key_id = GetCryptoRevision();
|
const auto master_key_id = GetCryptoRevision();
|
||||||
|
|
||||||
u128 rights_id{};
|
u128 rights_id{};
|
||||||
memcpy(rights_id.data(), header.rights_id.data(), 16);
|
memcpy(rights_id.data(), header.rights_id.data(), 16);
|
||||||
if (rights_id == u128{}) {
|
if (rights_id == u128{}) {
|
||||||
status = Loader::ResultStatus::ErrorInvalidRightsID;
|
status = Loader::ResultStatus::ErrorInvalidRightsID;
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
|
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
|
||||||
if (titlekey == Core::Crypto::Key128{}) {
|
if (titlekey == Core::Crypto::Key128{}) {
|
||||||
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
|
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
|
||||||
status = Loader::ResultStatus::ErrorMissingTitlekek;
|
status = Loader::ResultStatus::ErrorMissingTitlekek;
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
|
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
|
||||||
|
@ -458,25 +457,25 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s
|
||||||
case NCASectionCryptoType::BKTR:
|
case NCASectionCryptoType::BKTR:
|
||||||
LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
|
LOG_DEBUG(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
|
||||||
{
|
{
|
||||||
boost::optional<Core::Crypto::Key128> key = boost::none;
|
std::optional<Core::Crypto::Key128> key = {};
|
||||||
if (has_rights_id) {
|
if (has_rights_id) {
|
||||||
status = Loader::ResultStatus::Success;
|
status = Loader::ResultStatus::Success;
|
||||||
key = GetTitlekey();
|
key = GetTitlekey();
|
||||||
if (key == boost::none) {
|
if (!key) {
|
||||||
if (status == Loader::ResultStatus::Success)
|
if (status == Loader::ResultStatus::Success)
|
||||||
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
status = Loader::ResultStatus::ErrorMissingTitlekey;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
key = GetKeyAreaKey(NCASectionCryptoType::CTR);
|
key = GetKeyAreaKey(NCASectionCryptoType::CTR);
|
||||||
if (key == boost::none) {
|
if (!key) {
|
||||||
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
|
status = Loader::ResultStatus::ErrorMissingKeyAreaKey;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(
|
auto out = std::make_shared<Core::Crypto::CTREncryptionLayer>(std::move(in), *key,
|
||||||
std::move(in), key.value(), starting_offset);
|
starting_offset);
|
||||||
std::vector<u8> iv(16);
|
std::vector<u8> iv(16);
|
||||||
for (u8 i = 0; i < 8; ++i)
|
for (u8 i = 0; i < 8; ++i)
|
||||||
iv[i] = s_header.raw.section_ctr[0x8 - i - 1];
|
iv[i] = s_header.raw.section_ctr[0x8 - i - 1];
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
@ -111,8 +112,8 @@ private:
|
||||||
bool ReadPFS0Section(const NCASectionHeader& section, const NCASectionTableEntry& entry);
|
bool ReadPFS0Section(const NCASectionHeader& section, const NCASectionTableEntry& entry);
|
||||||
|
|
||||||
u8 GetCryptoRevision() const;
|
u8 GetCryptoRevision() const;
|
||||||
boost::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
|
std::optional<Core::Crypto::Key128> GetKeyAreaKey(NCASectionCryptoType type) const;
|
||||||
boost::optional<Core::Crypto::Key128> GetTitlekey();
|
std::optional<Core::Crypto::Key128> GetTitlekey();
|
||||||
VirtualFile Decrypt(const NCASectionHeader& header, VirtualFile in, u64 starting_offset);
|
VirtualFile Decrypt(const NCASectionHeader& header, VirtualFile in, u64 starting_offset);
|
||||||
|
|
||||||
std::vector<VirtualDir> dirs;
|
std::vector<VirtualDir> dirs;
|
||||||
|
|
|
@ -103,12 +103,12 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) {
|
||||||
offset += sizeof(u16);
|
offset += sizeof(u16);
|
||||||
|
|
||||||
const auto data = ips->ReadByte(offset++);
|
const auto data = ips->ReadByte(offset++);
|
||||||
if (data == boost::none)
|
if (!data)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (real_offset + rle_size > in_data.size())
|
if (real_offset + rle_size > in_data.size())
|
||||||
rle_size = static_cast<u16>(in_data.size() - real_offset);
|
rle_size = static_cast<u16>(in_data.size() - real_offset);
|
||||||
std::memset(in_data.data() + real_offset, data.get(), rle_size);
|
std::memset(in_data.data() + real_offset, *data, rle_size);
|
||||||
} else { // Standard Patch
|
} else { // Standard Patch
|
||||||
auto read = data_size;
|
auto read = data_size;
|
||||||
if (real_offset + read > in_data.size())
|
if (real_offset + read > in_data.size())
|
||||||
|
|
|
@ -65,7 +65,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
||||||
if (update != nullptr && update->GetExeFS() != nullptr &&
|
if (update != nullptr && update->GetExeFS() != nullptr &&
|
||||||
update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
|
update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
|
||||||
LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
|
LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
|
||||||
FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
|
FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
|
||||||
exefs = update->GetExeFS();
|
exefs = update->GetExeFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
|
||||||
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
|
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
|
||||||
new_nca->GetRomFS() != nullptr) {
|
new_nca->GetRomFS() != nullptr) {
|
||||||
LOG_INFO(Loader, " RomFS: Update ({}) applied successfully",
|
LOG_INFO(Loader, " RomFS: Update ({}) applied successfully",
|
||||||
FormatTitleVersion(installed->GetEntryVersion(update_tid).get_value_or(0)));
|
FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0)));
|
||||||
romfs = new_nca->GetRomFS();
|
romfs = new_nca->GetRomFS();
|
||||||
}
|
}
|
||||||
} else if (update_raw != nullptr) {
|
} else if (update_raw != nullptr) {
|
||||||
|
@ -280,12 +280,11 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
|
||||||
} else {
|
} else {
|
||||||
if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
|
if (installed->HasEntry(update_tid, ContentRecordType::Program)) {
|
||||||
const auto meta_ver = installed->GetEntryVersion(update_tid);
|
const auto meta_ver = installed->GetEntryVersion(update_tid);
|
||||||
if (meta_ver == boost::none || meta_ver.get() == 0) {
|
if (meta_ver.value_or(0) == 0) {
|
||||||
out.insert_or_assign("Update", "");
|
out.insert_or_assign("Update", "");
|
||||||
} else {
|
} else {
|
||||||
out.insert_or_assign(
|
out.insert_or_assign(
|
||||||
"Update",
|
"Update", FormatTitleVersion(*meta_ver, TitleVersionFormat::ThreeElements));
|
||||||
FormatTitleVersion(meta_ver.get(), TitleVersionFormat::ThreeElements));
|
|
||||||
}
|
}
|
||||||
} else if (update_raw != nullptr) {
|
} else if (update_raw != nullptr) {
|
||||||
out.insert_or_assign("Update", "PACKED");
|
out.insert_or_assign("Update", "PACKED");
|
||||||
|
|
|
@ -159,28 +159,28 @@ VirtualFile RegisteredCache::GetFileAtID(NcaID id) const {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boost::optional<NcaID> CheckMapForContentRecord(
|
static std::optional<NcaID> CheckMapForContentRecord(
|
||||||
const boost::container::flat_map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
|
const boost::container::flat_map<u64, CNMT>& map, u64 title_id, ContentRecordType type) {
|
||||||
if (map.find(title_id) == map.end())
|
if (map.find(title_id) == map.end())
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
const auto& cnmt = map.at(title_id);
|
const auto& cnmt = map.at(title_id);
|
||||||
|
|
||||||
const auto iter = std::find_if(cnmt.GetContentRecords().begin(), cnmt.GetContentRecords().end(),
|
const auto iter = std::find_if(cnmt.GetContentRecords().begin(), cnmt.GetContentRecords().end(),
|
||||||
[type](const ContentRecord& rec) { return rec.type == type; });
|
[type](const ContentRecord& rec) { return rec.type == type; });
|
||||||
if (iter == cnmt.GetContentRecords().end())
|
if (iter == cnmt.GetContentRecords().end())
|
||||||
return boost::none;
|
return {};
|
||||||
|
|
||||||
return boost::make_optional(iter->nca_id);
|
return std::make_optional(iter->nca_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
|
std::optional<NcaID> RegisteredCache::GetNcaIDFromMetadata(u64 title_id,
|
||||||
ContentRecordType type) const {
|
ContentRecordType type) const {
|
||||||
if (type == ContentRecordType::Meta && meta_id.find(title_id) != meta_id.end())
|
if (type == ContentRecordType::Meta && meta_id.find(title_id) != meta_id.end())
|
||||||
return meta_id.at(title_id);
|
return meta_id.at(title_id);
|
||||||
|
|
||||||
const auto res1 = CheckMapForContentRecord(yuzu_meta, title_id, type);
|
const auto res1 = CheckMapForContentRecord(yuzu_meta, title_id, type);
|
||||||
if (res1 != boost::none)
|
if (res1)
|
||||||
return res1;
|
return res1;
|
||||||
return CheckMapForContentRecord(meta, title_id, type);
|
return CheckMapForContentRecord(meta, title_id, type);
|
||||||
}
|
}
|
||||||
|
@ -283,17 +283,14 @@ bool RegisteredCache::HasEntry(RegisteredCacheEntry entry) const {
|
||||||
|
|
||||||
VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
|
VirtualFile RegisteredCache::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
|
||||||
const auto id = GetNcaIDFromMetadata(title_id, type);
|
const auto id = GetNcaIDFromMetadata(title_id, type);
|
||||||
if (id == boost::none)
|
return id ? GetFileAtID(*id) : nullptr;
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return GetFileAtID(id.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const {
|
VirtualFile RegisteredCache::GetEntryUnparsed(RegisteredCacheEntry entry) const {
|
||||||
return GetEntryUnparsed(entry.title_id, entry.type);
|
return GetEntryUnparsed(entry.title_id, entry.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
|
std::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
|
||||||
const auto meta_iter = meta.find(title_id);
|
const auto meta_iter = meta.find(title_id);
|
||||||
if (meta_iter != meta.end())
|
if (meta_iter != meta.end())
|
||||||
return meta_iter->second.GetTitleVersion();
|
return meta_iter->second.GetTitleVersion();
|
||||||
|
@ -302,15 +299,12 @@ boost::optional<u32> RegisteredCache::GetEntryVersion(u64 title_id) const {
|
||||||
if (yuzu_meta_iter != yuzu_meta.end())
|
if (yuzu_meta_iter != yuzu_meta.end())
|
||||||
return yuzu_meta_iter->second.GetTitleVersion();
|
return yuzu_meta_iter->second.GetTitleVersion();
|
||||||
|
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
|
VirtualFile RegisteredCache::GetEntryRaw(u64 title_id, ContentRecordType type) const {
|
||||||
const auto id = GetNcaIDFromMetadata(title_id, type);
|
const auto id = GetNcaIDFromMetadata(title_id, type);
|
||||||
if (id == boost::none)
|
return id ? parser(GetFileAtID(*id), *id) : nullptr;
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return parser(GetFileAtID(id.get()), id.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RegisteredCache::GetEntryRaw(RegisteredCacheEntry entry) const {
|
VirtualFile RegisteredCache::GetEntryRaw(RegisteredCacheEntry entry) const {
|
||||||
|
@ -364,8 +358,8 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntries() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
|
std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
|
||||||
boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
|
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
|
||||||
boost::optional<u64> title_id) const {
|
std::optional<u64> title_id) const {
|
||||||
std::vector<RegisteredCacheEntry> out;
|
std::vector<RegisteredCacheEntry> out;
|
||||||
IterateAllMetadata<RegisteredCacheEntry>(
|
IterateAllMetadata<RegisteredCacheEntry>(
|
||||||
out,
|
out,
|
||||||
|
@ -373,11 +367,11 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter(
|
||||||
return RegisteredCacheEntry{c.GetTitleID(), r.type};
|
return RegisteredCacheEntry{c.GetTitleID(), r.type};
|
||||||
},
|
},
|
||||||
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
|
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
|
||||||
if (title_type != boost::none && title_type.get() != c.GetType())
|
if (title_type && *title_type != c.GetType())
|
||||||
return false;
|
return false;
|
||||||
if (record_type != boost::none && record_type.get() != r.type)
|
if (record_type && *record_type != r.type)
|
||||||
return false;
|
return false;
|
||||||
if (title_id != boost::none && title_id.get() != c.GetTitleID())
|
if (title_id && *title_id != c.GetTitleID())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -459,7 +453,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NCA> nca, TitleType
|
||||||
|
|
||||||
InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
|
InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
|
||||||
bool overwrite_if_exists,
|
bool overwrite_if_exists,
|
||||||
boost::optional<NcaID> override_id) {
|
std::optional<NcaID> override_id) {
|
||||||
const auto in = nca->GetBaseFile();
|
const auto in = nca->GetBaseFile();
|
||||||
Core::Crypto::SHA256Hash hash{};
|
Core::Crypto::SHA256Hash hash{};
|
||||||
|
|
||||||
|
@ -468,12 +462,12 @@ InstallResult RegisteredCache::RawInstallNCA(std::shared_ptr<NCA> nca, const Vfs
|
||||||
// game is massive), we're going to cheat and only hash the first MB of the NCA.
|
// game is massive), we're going to cheat and only hash the first MB of the NCA.
|
||||||
// Also, for XCIs the NcaID matters, so if the override id isn't none, use that.
|
// Also, for XCIs the NcaID matters, so if the override id isn't none, use that.
|
||||||
NcaID id{};
|
NcaID id{};
|
||||||
if (override_id == boost::none) {
|
if (override_id) {
|
||||||
|
id = *override_id;
|
||||||
|
} else {
|
||||||
const auto& data = in->ReadBytes(0x100000);
|
const auto& data = in->ReadBytes(0x100000);
|
||||||
mbedtls_sha256(data.data(), data.size(), hash.data(), 0);
|
mbedtls_sha256(data.data(), data.size(), hash.data(), 0);
|
||||||
memcpy(id.data(), hash.data(), 16);
|
memcpy(id.data(), hash.data(), 16);
|
||||||
} else {
|
|
||||||
id = override_id.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path = GetRelativePathFromNcaID(id, false, true);
|
std::string path = GetRelativePathFromNcaID(id, false, true);
|
||||||
|
@ -543,14 +537,14 @@ bool RegisteredCacheUnion::HasEntry(RegisteredCacheEntry entry) const {
|
||||||
return HasEntry(entry.title_id, entry.type);
|
return HasEntry(entry.title_id, entry.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
|
std::optional<u32> RegisteredCacheUnion::GetEntryVersion(u64 title_id) const {
|
||||||
for (const auto& c : caches) {
|
for (const auto& c : caches) {
|
||||||
const auto res = c->GetEntryVersion(title_id);
|
const auto res = c->GetEntryVersion(title_id);
|
||||||
if (res != boost::none)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
|
VirtualFile RegisteredCacheUnion::GetEntryUnparsed(u64 title_id, ContentRecordType type) const {
|
||||||
|
@ -609,8 +603,8 @@ std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntries() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
|
std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
|
||||||
boost::optional<TitleType> title_type, boost::optional<ContentRecordType> record_type,
|
std::optional<TitleType> title_type, std::optional<ContentRecordType> record_type,
|
||||||
boost::optional<u64> title_id) const {
|
std::optional<u64> title_id) const {
|
||||||
std::vector<RegisteredCacheEntry> out;
|
std::vector<RegisteredCacheEntry> out;
|
||||||
for (const auto& c : caches) {
|
for (const auto& c : caches) {
|
||||||
c->IterateAllMetadata<RegisteredCacheEntry>(
|
c->IterateAllMetadata<RegisteredCacheEntry>(
|
||||||
|
@ -619,11 +613,11 @@ std::vector<RegisteredCacheEntry> RegisteredCacheUnion::ListEntriesFilter(
|
||||||
return RegisteredCacheEntry{c.GetTitleID(), r.type};
|
return RegisteredCacheEntry{c.GetTitleID(), r.type};
|
||||||
},
|
},
|
||||||
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
|
[&title_type, &record_type, &title_id](const CNMT& c, const ContentRecord& r) {
|
||||||
if (title_type != boost::none && title_type.get() != c.GetType())
|
if (title_type && *title_type != c.GetType())
|
||||||
return false;
|
return false;
|
||||||
if (record_type != boost::none && record_type.get() != r.type)
|
if (record_type && *record_type != r.type)
|
||||||
return false;
|
return false;
|
||||||
if (title_id != boost::none && title_id.get() != c.GetTitleID())
|
if (title_id && *title_id != c.GetTitleID())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
bool HasEntry(u64 title_id, ContentRecordType type) const;
|
bool HasEntry(u64 title_id, ContentRecordType type) const;
|
||||||
bool HasEntry(RegisteredCacheEntry entry) const;
|
bool HasEntry(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
boost::optional<u32> GetEntryVersion(u64 title_id) const;
|
std::optional<u32> GetEntryVersion(u64 title_id) const;
|
||||||
|
|
||||||
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
||||||
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
||||||
|
@ -96,11 +96,10 @@ public:
|
||||||
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
|
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
std::vector<RegisteredCacheEntry> ListEntries() const;
|
std::vector<RegisteredCacheEntry> ListEntries() const;
|
||||||
// If a parameter is not boost::none, it will be filtered for from all entries.
|
// If a parameter is not std::nullopt, it will be filtered for from all entries.
|
||||||
std::vector<RegisteredCacheEntry> ListEntriesFilter(
|
std::vector<RegisteredCacheEntry> ListEntriesFilter(
|
||||||
boost::optional<TitleType> title_type = boost::none,
|
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
|
||||||
boost::optional<ContentRecordType> record_type = boost::none,
|
std::optional<u64> title_id = {}) const;
|
||||||
boost::optional<u64> title_id = boost::none) const;
|
|
||||||
|
|
||||||
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
|
// Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure
|
||||||
// there is a meta NCA and all of them are accessible.
|
// there is a meta NCA and all of them are accessible.
|
||||||
|
@ -125,12 +124,11 @@ private:
|
||||||
std::vector<NcaID> AccumulateFiles() const;
|
std::vector<NcaID> AccumulateFiles() const;
|
||||||
void ProcessFiles(const std::vector<NcaID>& ids);
|
void ProcessFiles(const std::vector<NcaID>& ids);
|
||||||
void AccumulateYuzuMeta();
|
void AccumulateYuzuMeta();
|
||||||
boost::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
|
std::optional<NcaID> GetNcaIDFromMetadata(u64 title_id, ContentRecordType type) const;
|
||||||
VirtualFile GetFileAtID(NcaID id) const;
|
VirtualFile GetFileAtID(NcaID id) const;
|
||||||
VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
|
VirtualFile OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const;
|
||||||
InstallResult RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
|
InstallResult RawInstallNCA(std::shared_ptr<NCA> nca, const VfsCopyFunction& copy,
|
||||||
bool overwrite_if_exists,
|
bool overwrite_if_exists, std::optional<NcaID> override_id = {});
|
||||||
boost::optional<NcaID> override_id = boost::none);
|
|
||||||
bool RawInstallYuzuMeta(const CNMT& cnmt);
|
bool RawInstallYuzuMeta(const CNMT& cnmt);
|
||||||
|
|
||||||
VirtualDir dir;
|
VirtualDir dir;
|
||||||
|
@ -153,7 +151,7 @@ public:
|
||||||
bool HasEntry(u64 title_id, ContentRecordType type) const;
|
bool HasEntry(u64 title_id, ContentRecordType type) const;
|
||||||
bool HasEntry(RegisteredCacheEntry entry) const;
|
bool HasEntry(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
boost::optional<u32> GetEntryVersion(u64 title_id) const;
|
std::optional<u32> GetEntryVersion(u64 title_id) const;
|
||||||
|
|
||||||
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const;
|
||||||
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
VirtualFile GetEntryUnparsed(RegisteredCacheEntry entry) const;
|
||||||
|
@ -165,11 +163,10 @@ public:
|
||||||
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
|
std::unique_ptr<NCA> GetEntry(RegisteredCacheEntry entry) const;
|
||||||
|
|
||||||
std::vector<RegisteredCacheEntry> ListEntries() const;
|
std::vector<RegisteredCacheEntry> ListEntries() const;
|
||||||
// If a parameter is not boost::none, it will be filtered for from all entries.
|
// If a parameter is not std::nullopt, it will be filtered for from all entries.
|
||||||
std::vector<RegisteredCacheEntry> ListEntriesFilter(
|
std::vector<RegisteredCacheEntry> ListEntriesFilter(
|
||||||
boost::optional<TitleType> title_type = boost::none,
|
std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},
|
||||||
boost::optional<ContentRecordType> record_type = boost::none,
|
std::optional<u64> title_id = {}) const;
|
||||||
boost::optional<u64> title_id = boost::none) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<RegisteredCache*> caches;
|
std::vector<RegisteredCache*> caches;
|
||||||
|
|
|
@ -167,13 +167,13 @@ std::string VfsFile::GetExtension() const {
|
||||||
|
|
||||||
VfsDirectory::~VfsDirectory() = default;
|
VfsDirectory::~VfsDirectory() = default;
|
||||||
|
|
||||||
boost::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
|
std::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
|
||||||
u8 out{};
|
u8 out{};
|
||||||
std::size_t size = Read(&out, 1, offset);
|
std::size_t size = Read(&out, 1, offset);
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> VfsFile::ReadBytes(std::size_t size, std::size_t offset) const {
|
std::vector<u8> VfsFile::ReadBytes(std::size_t size, std::size_t offset) const {
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/vfs_types.h"
|
#include "core/file_sys/vfs_types.h"
|
||||||
|
|
||||||
|
@ -103,8 +105,8 @@ public:
|
||||||
// into file. Returns number of bytes successfully written.
|
// into file. Returns number of bytes successfully written.
|
||||||
virtual std::size_t Write(const u8* data, std::size_t length, std::size_t offset = 0) = 0;
|
virtual std::size_t Write(const u8* data, std::size_t length, std::size_t offset = 0) = 0;
|
||||||
|
|
||||||
// Reads exactly one byte at the offset provided, returning boost::none on error.
|
// Reads exactly one byte at the offset provided, returning std::nullopt on error.
|
||||||
virtual boost::optional<u8> ReadByte(std::size_t offset = 0) const;
|
virtual std::optional<u8> ReadByte(std::size_t offset = 0) const;
|
||||||
// Reads size bytes starting at offset in file into a vector.
|
// Reads size bytes starting at offset in file into a vector.
|
||||||
virtual std::vector<u8> ReadBytes(std::size_t size, std::size_t offset = 0) const;
|
virtual std::vector<u8> ReadBytes(std::size_t size, std::size_t offset = 0) const;
|
||||||
// Reads all the bytes from the file into a vector. Equivalent to 'file->Read(file->GetSize(),
|
// Reads all the bytes from the file into a vector. Equivalent to 'file->Read(file->GetSize(),
|
||||||
|
|
|
@ -57,11 +57,11 @@ std::size_t OffsetVfsFile::Write(const u8* data, std::size_t length, std::size_t
|
||||||
return file->Write(data, TrimToFit(length, r_offset), offset + r_offset);
|
return file->Write(data, TrimToFit(length, r_offset), offset + r_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
|
std::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
|
||||||
if (r_offset < size)
|
if (r_offset < size)
|
||||||
return file->ReadByte(offset + r_offset);
|
return file->ReadByte(offset + r_offset);
|
||||||
|
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> OffsetVfsFile::ReadBytes(std::size_t r_size, std::size_t r_offset) const {
|
std::vector<u8> OffsetVfsFile::ReadBytes(std::size_t r_size, std::size_t r_offset) const {
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
bool IsReadable() const override;
|
bool IsReadable() const override;
|
||||||
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
|
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
|
||||||
std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
|
std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override;
|
||||||
boost::optional<u8> ReadByte(std::size_t offset) const override;
|
std::optional<u8> ReadByte(std::size_t offset) const override;
|
||||||
std::vector<u8> ReadBytes(std::size_t size, std::size_t offset) const override;
|
std::vector<u8> ReadBytes(std::size_t size, std::size_t offset) const override;
|
||||||
std::vector<u8> ReadAllBytes() const override;
|
std::vector<u8> ReadAllBytes() const override;
|
||||||
bool WriteByte(u8 data, std::size_t offset) override;
|
bool WriteByte(u8 data, std::size_t offset) override;
|
||||||
|
|
|
@ -53,10 +53,10 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u8> ReadByte(std::size_t offset) const override {
|
std::optional<u8> ReadByte(std::size_t offset) const override {
|
||||||
if (offset < size)
|
if (offset < size)
|
||||||
return value;
|
return value;
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> ReadBytes(std::size_t length, std::size_t offset) const override {
|
std::vector<u8> ReadBytes(std::size_t length, std::size_t offset) const override {
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
@ -94,7 +94,7 @@ void Thread::CancelWakeupTimer() {
|
||||||
CoreTiming::UnscheduleEventThreadsafe(kernel.ThreadWakeupCallbackEventType(), callback_handle);
|
CoreTiming::UnscheduleEventThreadsafe(kernel.ThreadWakeupCallbackEventType(), callback_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boost::optional<s32> GetNextProcessorId(u64 mask) {
|
static std::optional<s32> GetNextProcessorId(u64 mask) {
|
||||||
for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) {
|
for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) {
|
||||||
if (mask & (1ULL << index)) {
|
if (mask & (1ULL << index)) {
|
||||||
if (!Core::System::GetInstance().Scheduler(index).GetCurrentThread()) {
|
if (!Core::System::GetInstance().Scheduler(index).GetCurrentThread()) {
|
||||||
|
@ -142,7 +142,7 @@ void Thread::ResumeFromWait() {
|
||||||
|
|
||||||
status = ThreadStatus::Ready;
|
status = ThreadStatus::Ready;
|
||||||
|
|
||||||
boost::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask);
|
std::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask);
|
||||||
if (!new_processor_id) {
|
if (!new_processor_id) {
|
||||||
new_processor_id = processor_id;
|
new_processor_id = processor_id;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ void Thread::ChangeCore(u32 core, u64 mask) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)};
|
std::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)};
|
||||||
|
|
||||||
if (!new_processor_id) {
|
if (!new_processor_id) {
|
||||||
new_processor_id = processor_id;
|
new_processor_id = processor_id;
|
||||||
|
|
|
@ -195,7 +195,7 @@ std::size_t ProfileManager::GetOpenUserCount() const {
|
||||||
|
|
||||||
/// Checks if a user id exists in our profile manager
|
/// Checks if a user id exists in our profile manager
|
||||||
bool ProfileManager::UserExists(UUID uuid) const {
|
bool ProfileManager::UserExists(UUID uuid) const {
|
||||||
return GetUserIndex(uuid) != std::nullopt;
|
return GetUserIndex(uuid).has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProfileManager::UserExistsIndex(std::size_t index) const {
|
bool ProfileManager::UserExistsIndex(std::size_t index) const {
|
||||||
|
|
|
@ -743,7 +743,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
Account::ProfileManager profile_manager{};
|
Account::ProfileManager profile_manager{};
|
||||||
const auto uuid = profile_manager.GetUser(Settings::values.current_user);
|
const auto uuid = profile_manager.GetUser(Settings::values.current_user);
|
||||||
ASSERT(uuid != std::nullopt);
|
ASSERT(uuid);
|
||||||
params.current_user = uuid->uuid;
|
params.current_user = uuid->uuid;
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
|
|
@ -31,7 +31,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer)
|
||||||
buffer_wait_event->Signal();
|
buffer_wait_event->Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
|
std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
|
||||||
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
|
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
|
||||||
// Only consider free buffers. Buffers become free once again after they've been Acquired
|
// Only consider free buffers. Buffers become free once again after they've been Acquired
|
||||||
// and Released by the compositor, see the NVFlinger::Compose method.
|
// and Released by the compositor, see the NVFlinger::Compose method.
|
||||||
|
@ -44,7 +44,7 @@ boost::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (itr == queue.end()) {
|
if (itr == queue.end()) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
itr->status = Buffer::Status::Dequeued;
|
itr->status = Buffer::Status::Dequeued;
|
||||||
|
@ -70,12 +70,12 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
|
||||||
itr->crop_rect = crop_rect;
|
itr->crop_rect = crop_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() {
|
std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() {
|
||||||
auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) {
|
auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) {
|
||||||
return buffer.status == Buffer::Status::Queued;
|
return buffer.status == Buffer::Status::Queued;
|
||||||
});
|
});
|
||||||
if (itr == queue.end())
|
if (itr == queue.end())
|
||||||
return boost::none;
|
return {};
|
||||||
itr->status = Buffer::Status::Acquired;
|
itr->status = Buffer::Status::Acquired;
|
||||||
return *itr;
|
return *itr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
|
@ -73,11 +74,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
|
void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
|
||||||
boost::optional<u32> DequeueBuffer(u32 width, u32 height);
|
std::optional<u32> DequeueBuffer(u32 width, u32 height);
|
||||||
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
const IGBPBuffer& RequestBuffer(u32 slot) const;
|
||||||
void QueueBuffer(u32 slot, BufferTransformFlags transform,
|
void QueueBuffer(u32 slot, BufferTransformFlags transform,
|
||||||
const MathUtil::Rectangle<int>& crop_rect);
|
const MathUtil::Rectangle<int>& crop_rect);
|
||||||
boost::optional<const Buffer&> AcquireBuffer();
|
std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer();
|
||||||
void ReleaseBuffer(u32 slot);
|
void ReleaseBuffer(u32 slot);
|
||||||
u32 Query(QueryType type);
|
u32 Query(QueryType type);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
@ -134,7 +134,7 @@ void NVFlinger::Compose() {
|
||||||
|
|
||||||
MicroProfileFlip();
|
MicroProfileFlip();
|
||||||
|
|
||||||
if (buffer == boost::none) {
|
if (!buffer) {
|
||||||
auto& system_instance = Core::System::GetInstance();
|
auto& system_instance = Core::System::GetInstance();
|
||||||
|
|
||||||
// There was no queued buffer to draw, render previous frame
|
// There was no queued buffer to draw, render previous frame
|
||||||
|
@ -143,7 +143,7 @@ void NVFlinger::Compose() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& igbp_buffer = buffer->igbp_buffer;
|
auto& igbp_buffer = buffer->get().igbp_buffer;
|
||||||
|
|
||||||
// Now send the buffer to the GPU for drawing.
|
// Now send the buffer to the GPU for drawing.
|
||||||
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
// TODO(Subv): Support more than just disp0. The display device selection is probably based
|
||||||
|
@ -152,10 +152,10 @@ void NVFlinger::Compose() {
|
||||||
ASSERT(nvdisp);
|
ASSERT(nvdisp);
|
||||||
|
|
||||||
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
|
||||||
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform,
|
igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride,
|
||||||
buffer->crop_rect);
|
buffer->get().transform, buffer->get().crop_rect);
|
||||||
|
|
||||||
buffer_queue->ReleaseBuffer(buffer->slot);
|
buffer_queue->ReleaseBuffer(buffer->get().slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
|
@ -506,9 +507,9 @@ private:
|
||||||
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
|
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
|
||||||
const u32 width{request.data.width};
|
const u32 width{request.data.width};
|
||||||
const u32 height{request.data.height};
|
const u32 height{request.data.height};
|
||||||
boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
||||||
|
|
||||||
if (slot != boost::none) {
|
if (slot) {
|
||||||
// Buffer is available
|
// Buffer is available
|
||||||
IGBPDequeueBufferResponseParcel response{*slot};
|
IGBPDequeueBufferResponseParcel response{*slot};
|
||||||
ctx.WriteBuffer(response.Serialize());
|
ctx.WriteBuffer(response.Serialize());
|
||||||
|
@ -520,7 +521,7 @@ private:
|
||||||
Kernel::ThreadWakeupReason reason) {
|
Kernel::ThreadWakeupReason reason) {
|
||||||
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
||||||
auto buffer_queue = nv_flinger->GetBufferQueue(id);
|
auto buffer_queue = nv_flinger->GetBufferQueue(id);
|
||||||
boost::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
|
||||||
IGBPDequeueBufferResponseParcel response{*slot};
|
IGBPDequeueBufferResponseParcel response{*slot};
|
||||||
ctx.WriteBuffer(response.Serialize());
|
ctx.WriteBuffer(response.Serialize());
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ public:
|
||||||
* information.
|
* information.
|
||||||
* @returns A pair with the optional system mode, and and the status.
|
* @returns A pair with the optional system mode, and and the status.
|
||||||
*/
|
*/
|
||||||
virtual std::pair<boost::optional<u32>, ResultStatus> LoadKernelSystemMode() {
|
virtual std::pair<std::optional<u32>, ResultStatus> LoadKernelSystemMode() {
|
||||||
// 96MB allocated to the application.
|
// 96MB allocated to the application.
|
||||||
return std::make_pair(2, ResultStatus::Success);
|
return std::make_pair(2, ResultStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Memory {
|
namespace Memory {
|
||||||
|
@ -18,19 +19,19 @@ namespace Memory {
|
||||||
*
|
*
|
||||||
* A hook may be mapped to multiple regions of memory.
|
* A hook may be mapped to multiple regions of memory.
|
||||||
*
|
*
|
||||||
* If a boost::none or false is returned from a function, the read/write request is passed through
|
* If a std::nullopt or false is returned from a function, the read/write request is passed through
|
||||||
* to the underlying memory region.
|
* to the underlying memory region.
|
||||||
*/
|
*/
|
||||||
class MemoryHook {
|
class MemoryHook {
|
||||||
public:
|
public:
|
||||||
virtual ~MemoryHook();
|
virtual ~MemoryHook();
|
||||||
|
|
||||||
virtual boost::optional<bool> IsValidAddress(VAddr addr) = 0;
|
virtual std::optional<bool> IsValidAddress(VAddr addr) = 0;
|
||||||
|
|
||||||
virtual boost::optional<u8> Read8(VAddr addr) = 0;
|
virtual std::optional<u8> Read8(VAddr addr) = 0;
|
||||||
virtual boost::optional<u16> Read16(VAddr addr) = 0;
|
virtual std::optional<u16> Read16(VAddr addr) = 0;
|
||||||
virtual boost::optional<u32> Read32(VAddr addr) = 0;
|
virtual std::optional<u32> Read32(VAddr addr) = 0;
|
||||||
virtual boost::optional<u64> Read64(VAddr addr) = 0;
|
virtual std::optional<u64> Read64(VAddr addr) = 0;
|
||||||
|
|
||||||
virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0;
|
virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0;
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,11 @@ void TestEnvironment::ClearWriteRecords() {
|
||||||
|
|
||||||
TestEnvironment::TestMemory::~TestMemory() {}
|
TestEnvironment::TestMemory::~TestMemory() {}
|
||||||
|
|
||||||
boost::optional<bool> TestEnvironment::TestMemory::IsValidAddress(VAddr addr) {
|
std::optional<bool> TestEnvironment::TestMemory::IsValidAddress(VAddr addr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u8> TestEnvironment::TestMemory::Read8(VAddr addr) {
|
std::optional<u8> TestEnvironment::TestMemory::Read8(VAddr addr) {
|
||||||
const auto iter = data.find(addr);
|
const auto iter = data.find(addr);
|
||||||
|
|
||||||
if (iter == data.end()) {
|
if (iter == data.end()) {
|
||||||
|
@ -79,15 +79,15 @@ boost::optional<u8> TestEnvironment::TestMemory::Read8(VAddr addr) {
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u16> TestEnvironment::TestMemory::Read16(VAddr addr) {
|
std::optional<u16> TestEnvironment::TestMemory::Read16(VAddr addr) {
|
||||||
return *Read8(addr) | static_cast<u16>(*Read8(addr + 1)) << 8;
|
return *Read8(addr) | static_cast<u16>(*Read8(addr + 1)) << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u32> TestEnvironment::TestMemory::Read32(VAddr addr) {
|
std::optional<u32> TestEnvironment::TestMemory::Read32(VAddr addr) {
|
||||||
return *Read16(addr) | static_cast<u32>(*Read16(addr + 2)) << 16;
|
return *Read16(addr) | static_cast<u32>(*Read16(addr + 2)) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u64> TestEnvironment::TestMemory::Read64(VAddr addr) {
|
std::optional<u64> TestEnvironment::TestMemory::Read64(VAddr addr) {
|
||||||
return *Read32(addr) | static_cast<u64>(*Read32(addr + 4)) << 32;
|
return *Read32(addr) | static_cast<u64>(*Read32(addr + 4)) << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,12 @@ private:
|
||||||
|
|
||||||
~TestMemory() override;
|
~TestMemory() override;
|
||||||
|
|
||||||
boost::optional<bool> IsValidAddress(VAddr addr) override;
|
std::optional<bool> IsValidAddress(VAddr addr) override;
|
||||||
|
|
||||||
boost::optional<u8> Read8(VAddr addr) override;
|
std::optional<u8> Read8(VAddr addr) override;
|
||||||
boost::optional<u16> Read16(VAddr addr) override;
|
std::optional<u16> Read16(VAddr addr) override;
|
||||||
boost::optional<u32> Read32(VAddr addr) override;
|
std::optional<u32> Read32(VAddr addr) override;
|
||||||
boost::optional<u64> Read64(VAddr addr) override;
|
std::optional<u64> Read64(VAddr addr) override;
|
||||||
|
|
||||||
bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) override;
|
bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) override;
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) {
|
||||||
for (auto entry : commands) {
|
for (auto entry : commands) {
|
||||||
Tegra::GPUVAddr address = entry.Address();
|
Tegra::GPUVAddr address = entry.Address();
|
||||||
u32 size = entry.sz;
|
u32 size = entry.sz;
|
||||||
const boost::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address);
|
const std::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address);
|
||||||
VAddr current_addr = *head_address;
|
VAddr current_addr = *head_address;
|
||||||
while (current_addr < *head_address + size * sizeof(CommandHeader)) {
|
while (current_addr < *head_address + size * sizeof(CommandHeader)) {
|
||||||
const CommandHeader header = {Memory::Read32(current_addr)};
|
const CommandHeader header = {Memory::Read32(current_addr)};
|
||||||
|
|
|
@ -167,7 +167,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||||
GPUVAddr sequence_address = regs.query.QueryAddress();
|
GPUVAddr sequence_address = regs.query.QueryAddress();
|
||||||
// Since the sequence address is given as a GPU VAddr, we have to convert it to an application
|
// Since the sequence address is given as a GPU VAddr, we have to convert it to an application
|
||||||
// VAddr before writing.
|
// VAddr before writing.
|
||||||
boost::optional<VAddr> address = memory_manager.GpuToCpuAddress(sequence_address);
|
std::optional<VAddr> address = memory_manager.GpuToCpuAddress(sequence_address);
|
||||||
|
|
||||||
// TODO(Subv): Support the other query units.
|
// TODO(Subv): Support the other query units.
|
||||||
ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,
|
ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,
|
||||||
|
@ -285,7 +285,7 @@ void Maxwell3D::ProcessCBData(u32 value) {
|
||||||
// Don't allow writing past the end of the buffer.
|
// Don't allow writing past the end of the buffer.
|
||||||
ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size);
|
ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size);
|
||||||
|
|
||||||
boost::optional<VAddr> address =
|
std::optional<VAddr> address =
|
||||||
memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos);
|
memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos);
|
||||||
|
|
||||||
Memory::Write32(*address, value);
|
Memory::Write32(*address, value);
|
||||||
|
@ -298,7 +298,7 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
||||||
GPUVAddr tic_base_address = regs.tic.TICAddress();
|
GPUVAddr tic_base_address = regs.tic.TICAddress();
|
||||||
|
|
||||||
GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry);
|
GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry);
|
||||||
boost::optional<VAddr> tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu);
|
std::optional<VAddr> tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu);
|
||||||
|
|
||||||
Texture::TICEntry tic_entry;
|
Texture::TICEntry tic_entry;
|
||||||
Memory::ReadBlock(*tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
|
Memory::ReadBlock(*tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
|
||||||
|
@ -322,7 +322,7 @@ Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
|
||||||
GPUVAddr tsc_base_address = regs.tsc.TSCAddress();
|
GPUVAddr tsc_base_address = regs.tsc.TSCAddress();
|
||||||
|
|
||||||
GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry);
|
GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry);
|
||||||
boost::optional<VAddr> tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu);
|
std::optional<VAddr> tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu);
|
||||||
|
|
||||||
Texture::TSCEntry tsc_entry;
|
Texture::TSCEntry tsc_entry;
|
||||||
Memory::ReadBlock(*tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry));
|
Memory::ReadBlock(*tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry));
|
||||||
|
@ -386,7 +386,7 @@ Texture::FullTextureInfo Maxwell3D::GetStageTexture(Regs::ShaderStage stage,
|
||||||
|
|
||||||
ASSERT(tex_info_address < tex_info_buffer.address + tex_info_buffer.size);
|
ASSERT(tex_info_address < tex_info_buffer.address + tex_info_buffer.size);
|
||||||
|
|
||||||
boost::optional<VAddr> tex_address_cpu = memory_manager.GpuToCpuAddress(tex_info_address);
|
std::optional<VAddr> tex_address_cpu = memory_manager.GpuToCpuAddress(tex_info_address);
|
||||||
Texture::TextureHandle tex_handle{Memory::Read32(*tex_address_cpu)};
|
Texture::TextureHandle tex_handle{Memory::Read32(*tex_address_cpu)};
|
||||||
|
|
||||||
Texture::FullTextureInfo tex_info{};
|
Texture::FullTextureInfo tex_info{};
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -1456,7 +1455,7 @@ public:
|
||||||
Type type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
static boost::optional<const Matcher&> Decode(Instruction instr) {
|
static std::optional<std::reference_wrapper<const Matcher>> Decode(Instruction instr) {
|
||||||
static const auto table{GetDecodeTable()};
|
static const auto table{GetDecodeTable()};
|
||||||
|
|
||||||
const auto matches_instruction = [instr](const auto& matcher) {
|
const auto matches_instruction = [instr](const auto& matcher) {
|
||||||
|
@ -1464,7 +1463,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
return iter != table.end() ? boost::optional<const Matcher&>(*iter) : boost::none;
|
return iter != table.end() ? std::optional<std::reference_wrapper<const Matcher>>(*iter)
|
||||||
|
: std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -29,7 +29,7 @@ void MacroInterpreter::Execute(const std::vector<u32>& code, std::vector<u32> pa
|
||||||
void MacroInterpreter::Reset() {
|
void MacroInterpreter::Reset() {
|
||||||
registers = {};
|
registers = {};
|
||||||
pc = 0;
|
pc = 0;
|
||||||
delayed_pc = boost::none;
|
delayed_pc = {};
|
||||||
method_address.raw = 0;
|
method_address.raw = 0;
|
||||||
parameters.clear();
|
parameters.clear();
|
||||||
// The next parameter index starts at 1, because $r1 already has the value of the first
|
// The next parameter index starts at 1, because $r1 already has the value of the first
|
||||||
|
@ -44,10 +44,10 @@ bool MacroInterpreter::Step(const std::vector<u32>& code, bool is_delay_slot) {
|
||||||
pc += 4;
|
pc += 4;
|
||||||
|
|
||||||
// Update the program counter if we were delayed
|
// Update the program counter if we were delayed
|
||||||
if (delayed_pc != boost::none) {
|
if (delayed_pc) {
|
||||||
ASSERT(is_delay_slot);
|
ASSERT(is_delay_slot);
|
||||||
pc = *delayed_pc;
|
pc = *delayed_pc;
|
||||||
delayed_pc = boost::none;
|
delayed_pc = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode.operation) {
|
switch (opcode.operation) {
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ private:
|
||||||
Engines::Maxwell3D& maxwell3d;
|
Engines::Maxwell3D& maxwell3d;
|
||||||
|
|
||||||
u32 pc; ///< Current program counter
|
u32 pc; ///< Current program counter
|
||||||
boost::optional<u32>
|
std::optional<u32>
|
||||||
delayed_pc; ///< Program counter to execute at after the delay slot is executed.
|
delayed_pc; ///< Program counter to execute at after the delay slot is executed.
|
||||||
|
|
||||||
static constexpr std::size_t NumMacroRegisters = 8;
|
static constexpr std::size_t NumMacroRegisters = 8;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
|
GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
|
||||||
boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, align);
|
std::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, align);
|
||||||
ASSERT(gpu_addr);
|
ASSERT(gpu_addr);
|
||||||
|
|
||||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||||
|
@ -34,7 +34,7 @@ GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
|
GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
|
||||||
boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, PAGE_SIZE);
|
std::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, PAGE_SIZE);
|
||||||
ASSERT(gpu_addr);
|
ASSERT(gpu_addr);
|
||||||
|
|
||||||
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
|
||||||
|
@ -97,7 +97,7 @@ GPUVAddr MemoryManager::GetRegionEnd(GPUVAddr region_start) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
|
std::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
|
||||||
GPUVAddr gpu_addr = 0;
|
GPUVAddr gpu_addr = 0;
|
||||||
u64 free_space = 0;
|
u64 free_space = 0;
|
||||||
align = (align + PAGE_MASK) & ~PAGE_MASK;
|
align = (align + PAGE_MASK) & ~PAGE_MASK;
|
||||||
|
@ -118,7 +118,7 @@ boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) {
|
std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) {
|
||||||
VAddr base_addr = PageSlot(gpu_addr);
|
VAddr base_addr = PageSlot(gpu_addr);
|
||||||
|
|
||||||
if (base_addr == static_cast<u64>(PageStatus::Allocated) ||
|
if (base_addr == static_cast<u64>(PageStatus::Allocated) ||
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
@ -27,7 +26,7 @@ public:
|
||||||
GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
|
GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
|
||||||
GPUVAddr UnmapBuffer(GPUVAddr gpu_addr, u64 size);
|
GPUVAddr UnmapBuffer(GPUVAddr gpu_addr, u64 size);
|
||||||
GPUVAddr GetRegionEnd(GPUVAddr region_start) const;
|
GPUVAddr GetRegionEnd(GPUVAddr region_start) const;
|
||||||
boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
|
std::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
|
||||||
std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;
|
std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;
|
||||||
|
|
||||||
static constexpr u64 PAGE_BITS = 16;
|
static constexpr u64 PAGE_BITS = 16;
|
||||||
|
@ -35,7 +34,7 @@ public:
|
||||||
static constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
|
static constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<GPUVAddr> FindFreeBlock(u64 size, u64 align = 1);
|
std::optional<GPUVAddr> FindFreeBlock(u64 size, u64 align = 1);
|
||||||
bool IsPageMapped(GPUVAddr gpu_addr);
|
bool IsPageMapped(GPUVAddr gpu_addr);
|
||||||
VAddr& PageSlot(GPUVAddr gpu_addr);
|
VAddr& PageSlot(GPUVAddr gpu_addr);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <boost/optional.hpp>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
|
@ -28,7 +29,8 @@ public:
|
||||||
virtual ~RendererBase();
|
virtual ~RendererBase();
|
||||||
|
|
||||||
/// Swap buffers (render frame)
|
/// Swap buffers (render frame)
|
||||||
virtual void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) = 0;
|
virtual void SwapBuffers(
|
||||||
|
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) = 0;
|
||||||
|
|
||||||
/// Initialize the renderer
|
/// Initialize the renderer
|
||||||
virtual bool Init() = 0;
|
virtual bool Init() = 0;
|
||||||
|
|
|
@ -17,7 +17,7 @@ OGLBufferCache::OGLBufferCache(std::size_t size) : stream_buffer(GL_ARRAY_BUFFER
|
||||||
GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size,
|
GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size,
|
||||||
std::size_t alignment, bool cache) {
|
std::size_t alignment, bool cache) {
|
||||||
auto& memory_manager = Core::System::GetInstance().GPU().MemoryManager();
|
auto& memory_manager = Core::System::GetInstance().GPU().MemoryManager();
|
||||||
const boost::optional<VAddr> cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
|
const std::optional<VAddr> cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
|
||||||
|
|
||||||
// Cache management is a big overhead, so only cache entries with a given size.
|
// Cache management is a big overhead, so only cache entries with a given size.
|
||||||
// TODO: Figure out which size is the best for given games.
|
// TODO: Figure out which size is the best for given games.
|
||||||
|
|
|
@ -45,7 +45,7 @@ GLintptr PrimitiveAssembler::MakeQuadIndexed(Tegra::GPUVAddr gpu_addr, std::size
|
||||||
auto [dst_pointer, index_offset] = buffer_cache.ReserveMemory(map_size);
|
auto [dst_pointer, index_offset] = buffer_cache.ReserveMemory(map_size);
|
||||||
|
|
||||||
auto& memory_manager = Core::System::GetInstance().GPU().MemoryManager();
|
auto& memory_manager = Core::System::GetInstance().GPU().MemoryManager();
|
||||||
const boost::optional<VAddr> cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
|
const std::optional<VAddr> cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr)};
|
||||||
const u8* source{Memory::GetPointer(*cpu_addr)};
|
const u8* source{Memory::GetPointer(*cpu_addr)};
|
||||||
|
|
||||||
for (u32 primitive = 0; primitive < count / 4; ++primitive) {
|
for (u32 primitive = 0; primitive < count / 4; ++primitive) {
|
||||||
|
|
|
@ -401,7 +401,7 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
|
||||||
|
|
||||||
void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
|
void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
|
||||||
bool preserve_contents,
|
bool preserve_contents,
|
||||||
boost::optional<std::size_t> single_color_target) {
|
std::optional<std::size_t> single_color_target) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
|
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
|
||||||
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/icl/interval_map.hpp>
|
#include <boost/icl/interval_map.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <boost/range/iterator_range.hpp>
|
#include <boost/range/iterator_range.hpp>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ private:
|
||||||
*/
|
*/
|
||||||
void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true,
|
void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true,
|
||||||
bool preserve_contents = true,
|
bool preserve_contents = true,
|
||||||
boost::optional<std::size_t> single_color_target = {});
|
std::optional<std::size_t> single_color_target = {});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configures the current constbuffers to use for the draw command.
|
* Configures the current constbuffers to use for the draw command.
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
@ -144,7 +144,7 @@ private:
|
||||||
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
||||||
const Instruction instr = {program_code[offset]};
|
const Instruction instr = {program_code[offset]};
|
||||||
if (const auto opcode = OpCode::Decode(instr)) {
|
if (const auto opcode = OpCode::Decode(instr)) {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::EXIT: {
|
case OpCode::Id::EXIT: {
|
||||||
// The EXIT instruction can be predicated, which means that the shader can
|
// The EXIT instruction can be predicated, which means that the shader can
|
||||||
// conditionally end on this instruction. We have to consider the case where the
|
// conditionally end on this instruction. We have to consider the case where the
|
||||||
|
@ -430,7 +430,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
|
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
|
||||||
const Tegra::Shader::IpaMode& input_mode,
|
const Tegra::Shader::IpaMode& input_mode,
|
||||||
boost::optional<Register> vertex = {}) {
|
std::optional<Register> vertex = {}) {
|
||||||
const std::string dest = GetRegisterAsFloat(reg);
|
const std::string dest = GetRegisterAsFloat(reg);
|
||||||
const std::string src = GetInputAttribute(attribute, input_mode, vertex) + GetSwizzle(elem);
|
const std::string src = GetInputAttribute(attribute, input_mode, vertex) + GetSwizzle(elem);
|
||||||
shader.AddLine(dest + " = " + src + ';');
|
shader.AddLine(dest + " = " + src + ';');
|
||||||
|
@ -807,10 +807,10 @@ private:
|
||||||
/// Generates code representing an input attribute register.
|
/// Generates code representing an input attribute register.
|
||||||
std::string GetInputAttribute(Attribute::Index attribute,
|
std::string GetInputAttribute(Attribute::Index attribute,
|
||||||
const Tegra::Shader::IpaMode& input_mode,
|
const Tegra::Shader::IpaMode& input_mode,
|
||||||
boost::optional<Register> vertex = {}) {
|
std::optional<Register> vertex = {}) {
|
||||||
auto GeometryPass = [&](const std::string& name) {
|
auto GeometryPass = [&](const std::string& name) {
|
||||||
if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) {
|
if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) {
|
||||||
return "gs_" + name + '[' + GetRegisterAsInteger(vertex.value(), 0, false) + ']';
|
return "gs_" + name + '[' + GetRegisterAsInteger(*vertex, 0, false) + ']';
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
@ -1465,7 +1465,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.AddLine(
|
shader.AddLine(
|
||||||
fmt::format("// {}: {} (0x{:016x})", offset, opcode->GetName(), instr.value));
|
fmt::format("// {}: {} (0x{:016x})", offset, opcode->get().GetName(), instr.value));
|
||||||
|
|
||||||
using Tegra::Shader::Pred;
|
using Tegra::Shader::Pred;
|
||||||
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
||||||
|
@ -1473,7 +1473,7 @@ private:
|
||||||
|
|
||||||
// Some instructions (like SSY) don't have a predicate field, they are always
|
// Some instructions (like SSY) don't have a predicate field, they are always
|
||||||
// unconditionally executed.
|
// unconditionally executed.
|
||||||
bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->GetId());
|
bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->get().GetId());
|
||||||
|
|
||||||
if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
|
if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
|
||||||
shader.AddLine("if (" +
|
shader.AddLine("if (" +
|
||||||
|
@ -1483,7 +1483,7 @@ private:
|
||||||
++shader.scope;
|
++shader.scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->GetType()) {
|
switch (opcode->get().GetType()) {
|
||||||
case OpCode::Type::Arithmetic: {
|
case OpCode::Type::Arithmetic: {
|
||||||
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
||||||
|
|
||||||
|
@ -1500,7 +1500,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::MOV_C:
|
case OpCode::Id::MOV_C:
|
||||||
case OpCode::Id::MOV_R: {
|
case OpCode::Id::MOV_R: {
|
||||||
// MOV does not have neither 'abs' nor 'neg' bits.
|
// MOV does not have neither 'abs' nor 'neg' bits.
|
||||||
|
@ -1600,14 +1600,15 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}",
|
||||||
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::ArithmeticImmediate: {
|
case OpCode::Type::ArithmeticImmediate: {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::MOV32_IMM: {
|
case OpCode::Id::MOV32_IMM: {
|
||||||
regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1);
|
regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1);
|
||||||
break;
|
break;
|
||||||
|
@ -1651,7 +1652,7 @@ private:
|
||||||
std::string op_a = instr.bfe.negate_a ? "-" : "";
|
std::string op_a = instr.bfe.negate_a ? "-" : "";
|
||||||
op_a += regs.GetRegisterAsInteger(instr.gpr8);
|
op_a += regs.GetRegisterAsInteger(instr.gpr8);
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::BFE_IMM: {
|
case OpCode::Id::BFE_IMM: {
|
||||||
std::string inner_shift =
|
std::string inner_shift =
|
||||||
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
|
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
|
||||||
|
@ -1663,7 +1664,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1685,7 +1686,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::SHR_C:
|
case OpCode::Id::SHR_C:
|
||||||
case OpCode::Id::SHR_R:
|
case OpCode::Id::SHR_R:
|
||||||
case OpCode::Id::SHR_IMM: {
|
case OpCode::Id::SHR_IMM: {
|
||||||
|
@ -1705,7 +1706,7 @@ private:
|
||||||
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
|
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1715,7 +1716,7 @@ private:
|
||||||
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
||||||
std::string op_b = std::to_string(instr.alu.imm20_32.Value());
|
std::string op_b = std::to_string(instr.alu.imm20_32.Value());
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::IADD32I:
|
case OpCode::Id::IADD32I:
|
||||||
if (instr.iadd32i.negate_a)
|
if (instr.iadd32i.negate_a)
|
||||||
op_a = "-(" + op_a + ')';
|
op_a = "-(" + op_a + ')';
|
||||||
|
@ -1737,7 +1738,7 @@ private:
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}",
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}",
|
||||||
opcode->GetName());
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1757,7 +1758,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::IADD_C:
|
case OpCode::Id::IADD_C:
|
||||||
case OpCode::Id::IADD_R:
|
case OpCode::Id::IADD_R:
|
||||||
case OpCode::Id::IADD_IMM: {
|
case OpCode::Id::IADD_IMM: {
|
||||||
|
@ -1793,7 +1794,7 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (opcode->GetId() == OpCode::Id::IADD3_R) {
|
if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
|
||||||
apply_height(instr.iadd3.height_a, op_a);
|
apply_height(instr.iadd3.height_a, op_a);
|
||||||
apply_height(instr.iadd3.height_b, op_b);
|
apply_height(instr.iadd3.height_b, op_b);
|
||||||
apply_height(instr.iadd3.height_c, op_c);
|
apply_height(instr.iadd3.height_c, op_c);
|
||||||
|
@ -1809,7 +1810,7 @@ private:
|
||||||
op_c = "-(" + op_c + ')';
|
op_c = "-(" + op_c + ')';
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
if (opcode->GetId() == OpCode::Id::IADD3_R) {
|
if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
|
||||||
switch (instr.iadd3.mode) {
|
switch (instr.iadd3.mode) {
|
||||||
case Tegra::Shader::IAdd3Mode::RightShift:
|
case Tegra::Shader::IAdd3Mode::RightShift:
|
||||||
// TODO(tech4me): According to
|
// TODO(tech4me): According to
|
||||||
|
@ -1884,7 +1885,7 @@ private:
|
||||||
const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
|
const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
|
||||||
std::string lut;
|
std::string lut;
|
||||||
|
|
||||||
if (opcode->GetId() == OpCode::Id::LOP3_R) {
|
if (opcode->get().GetId() == OpCode::Id::LOP3_R) {
|
||||||
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
|
||||||
} else {
|
} else {
|
||||||
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')';
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')';
|
||||||
|
@ -1914,7 +1915,7 @@ private:
|
||||||
case OpCode::Id::LEA_HI: {
|
case OpCode::Id::LEA_HI: {
|
||||||
std::string op_c;
|
std::string op_c;
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::LEA_R2: {
|
case OpCode::Id::LEA_R2: {
|
||||||
op_a = regs.GetRegisterAsInteger(instr.gpr20);
|
op_a = regs.GetRegisterAsInteger(instr.gpr20);
|
||||||
op_b = regs.GetRegisterAsInteger(instr.gpr39);
|
op_b = regs.GetRegisterAsInteger(instr.gpr39);
|
||||||
|
@ -1959,7 +1960,8 @@ private:
|
||||||
op_b = regs.GetRegisterAsInteger(instr.gpr8);
|
op_b = regs.GetRegisterAsInteger(instr.gpr8);
|
||||||
op_a = std::to_string(instr.lea.imm.entry_a);
|
op_a = std::to_string(instr.lea.imm.entry_a);
|
||||||
op_c = std::to_string(instr.lea.imm.entry_b);
|
op_c = std::to_string(instr.lea.imm.entry_b);
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}",
|
||||||
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1974,7 +1976,7 @@ private:
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
|
||||||
opcode->GetName());
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1982,20 +1984,21 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::ArithmeticHalf: {
|
case OpCode::Type::ArithmeticHalf: {
|
||||||
if (opcode->GetId() == OpCode::Id::HADD2_C || opcode->GetId() == OpCode::Id::HADD2_R) {
|
if (opcode->get().GetId() == OpCode::Id::HADD2_C ||
|
||||||
|
opcode->get().GetId() == OpCode::Id::HADD2_R) {
|
||||||
ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented");
|
ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented");
|
||||||
}
|
}
|
||||||
const bool negate_a =
|
const bool negate_a =
|
||||||
opcode->GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0;
|
opcode->get().GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0;
|
||||||
const bool negate_b =
|
const bool negate_b =
|
||||||
opcode->GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
||||||
|
|
||||||
const std::string op_a =
|
const std::string op_a =
|
||||||
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.alu_half.type_a,
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.alu_half.type_a,
|
||||||
instr.alu_half.abs_a != 0, negate_a);
|
instr.alu_half.abs_a != 0, negate_a);
|
||||||
|
|
||||||
std::string op_b;
|
std::string op_b;
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HADD2_C:
|
case OpCode::Id::HADD2_C:
|
||||||
case OpCode::Id::HMUL2_C:
|
case OpCode::Id::HMUL2_C:
|
||||||
op_b = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
op_b = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
||||||
|
@ -2013,7 +2016,7 @@ private:
|
||||||
op_b = GetHalfFloat(op_b, instr.alu_half.type_b, instr.alu_half.abs_b != 0, negate_b);
|
op_b = GetHalfFloat(op_b, instr.alu_half.type_b, instr.alu_half.abs_b != 0, negate_b);
|
||||||
|
|
||||||
const std::string result = [&]() {
|
const std::string result = [&]() {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HADD2_C:
|
case OpCode::Id::HADD2_C:
|
||||||
case OpCode::Id::HADD2_R:
|
case OpCode::Id::HADD2_R:
|
||||||
return '(' + op_a + " + " + op_b + ')';
|
return '(' + op_a + " + " + op_b + ')';
|
||||||
|
@ -2021,7 +2024,8 @@ private:
|
||||||
case OpCode::Id::HMUL2_R:
|
case OpCode::Id::HMUL2_R:
|
||||||
return '(' + op_a + " * " + op_b + ')';
|
return '(' + op_a + " * " + op_b + ')';
|
||||||
default:
|
default:
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}",
|
||||||
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return std::string("0");
|
return std::string("0");
|
||||||
}
|
}
|
||||||
|
@ -2032,7 +2036,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::ArithmeticHalfImmediate: {
|
case OpCode::Type::ArithmeticHalfImmediate: {
|
||||||
if (opcode->GetId() == OpCode::Id::HADD2_IMM) {
|
if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) {
|
||||||
ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented");
|
ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented");
|
||||||
} else {
|
} else {
|
||||||
ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None,
|
ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None,
|
||||||
|
@ -2046,7 +2050,7 @@ private:
|
||||||
const std::string op_b = UnpackHalfImmediate(instr, true);
|
const std::string op_b = UnpackHalfImmediate(instr, true);
|
||||||
|
|
||||||
const std::string result = [&]() {
|
const std::string result = [&]() {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HADD2_IMM:
|
case OpCode::Id::HADD2_IMM:
|
||||||
return op_a + " + " + op_b;
|
return op_a + " + " + op_b;
|
||||||
case OpCode::Id::HMUL2_IMM:
|
case OpCode::Id::HMUL2_IMM:
|
||||||
|
@ -2072,7 +2076,7 @@ private:
|
||||||
ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented",
|
ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented",
|
||||||
instr.ffma.tab5980_1.Value());
|
instr.ffma.tab5980_1.Value());
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::FFMA_CR: {
|
case OpCode::Id::FFMA_CR: {
|
||||||
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
||||||
GLSLRegister::Type::Float);
|
GLSLRegister::Type::Float);
|
||||||
|
@ -2096,7 +2100,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2107,14 +2111,14 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::Hfma2: {
|
case OpCode::Type::Hfma2: {
|
||||||
if (opcode->GetId() == OpCode::Id::HFMA2_RR) {
|
if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) {
|
||||||
ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None,
|
ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None,
|
||||||
"Unimplemented");
|
"Unimplemented");
|
||||||
} else {
|
} else {
|
||||||
ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None,
|
ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None,
|
||||||
"Unimplemented");
|
"Unimplemented");
|
||||||
}
|
}
|
||||||
const bool saturate = opcode->GetId() == OpCode::Id::HFMA2_RR
|
const bool saturate = opcode->get().GetId() == OpCode::Id::HFMA2_RR
|
||||||
? instr.hfma2.rr.saturate != 0
|
? instr.hfma2.rr.saturate != 0
|
||||||
: instr.hfma2.saturate != 0;
|
: instr.hfma2.saturate != 0;
|
||||||
|
|
||||||
|
@ -2122,7 +2126,7 @@ private:
|
||||||
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hfma2.type_a);
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hfma2.type_a);
|
||||||
std::string op_b, op_c;
|
std::string op_b, op_c;
|
||||||
|
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HFMA2_CR:
|
case OpCode::Id::HFMA2_CR:
|
||||||
op_b = GetHalfFloat(regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
op_b = GetHalfFloat(regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
||||||
GLSLRegister::Type::UnsignedInteger),
|
GLSLRegister::Type::UnsignedInteger),
|
||||||
|
@ -2160,7 +2164,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::Conversion: {
|
case OpCode::Type::Conversion: {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::I2I_R: {
|
case OpCode::Id::I2I_R: {
|
||||||
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
|
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
|
||||||
|
|
||||||
|
@ -2298,14 +2302,15 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}",
|
||||||
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::Memory: {
|
case OpCode::Type::Memory: {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::LD_A: {
|
case OpCode::Id::LD_A: {
|
||||||
// Note: Shouldn't this be interp mode flat? As in no interpolation made.
|
// Note: Shouldn't this be interp mode flat? As in no interpolation made.
|
||||||
ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
|
ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
|
||||||
|
@ -2949,7 +2954,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3043,7 +3048,7 @@ private:
|
||||||
instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
||||||
|
|
||||||
const std::string op_b = [&]() {
|
const std::string op_b = [&]() {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HSETP2_R:
|
case OpCode::Id::HSETP2_R:
|
||||||
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
||||||
instr.hsetp2.type_b, instr.hsetp2.abs_a,
|
instr.hsetp2.type_b, instr.hsetp2.abs_a,
|
||||||
|
@ -3105,7 +3110,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Type::PredicateSetPredicate: {
|
case OpCode::Type::PredicateSetPredicate: {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::PSETP: {
|
case OpCode::Id::PSETP: {
|
||||||
const std::string op_a =
|
const std::string op_a =
|
||||||
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
|
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
|
||||||
|
@ -3151,7 +3156,8 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}",
|
||||||
|
opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3239,7 +3245,7 @@ private:
|
||||||
instr.hset2.abs_a != 0, instr.hset2.negate_a != 0);
|
instr.hset2.abs_a != 0, instr.hset2.negate_a != 0);
|
||||||
|
|
||||||
const std::string op_b = [&]() {
|
const std::string op_b = [&]() {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HSET2_R:
|
case OpCode::Id::HSET2_R:
|
||||||
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
||||||
instr.hset2.type_b, instr.hset2.abs_b != 0,
|
instr.hset2.type_b, instr.hset2.abs_b != 0,
|
||||||
|
@ -3288,7 +3294,7 @@ private:
|
||||||
const bool is_signed{instr.xmad.sign_a == 1};
|
const bool is_signed{instr.xmad.sign_a == 1};
|
||||||
|
|
||||||
bool is_merge{};
|
bool is_merge{};
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::XMAD_CR: {
|
case OpCode::Id::XMAD_CR: {
|
||||||
is_merge = instr.xmad.merge_56;
|
is_merge = instr.xmad.merge_56;
|
||||||
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
||||||
|
@ -3317,7 +3323,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3369,7 +3375,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
switch (opcode->GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::EXIT: {
|
case OpCode::Id::EXIT: {
|
||||||
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
|
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
|
||||||
EmitFragmentOutputsWrite();
|
EmitFragmentOutputsWrite();
|
||||||
|
@ -3564,7 +3570,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->GetName());
|
LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->get().GetName());
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3705,9 +3711,9 @@ std::string GetCommonDeclarations() {
|
||||||
RasterizerOpenGL::MaxConstbufferSize / sizeof(GLvec4));
|
RasterizerOpenGL::MaxConstbufferSize / sizeof(GLvec4));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
||||||
Maxwell3D::Regs::ShaderStage stage,
|
Maxwell3D::Regs::ShaderStage stage,
|
||||||
const std::string& suffix) {
|
const std::string& suffix) {
|
||||||
try {
|
try {
|
||||||
const auto subroutines =
|
const auto subroutines =
|
||||||
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
|
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
|
||||||
|
@ -3716,7 +3722,7 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
|
||||||
} catch (const DecompileFail& exception) {
|
} catch (const DecompileFail& exception) {
|
||||||
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
||||||
}
|
}
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace OpenGL::GLShader::Decompiler
|
} // namespace OpenGL::GLShader::Decompiler
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
#include "video_core/renderer_opengl/gl_shader_gen.h"
|
||||||
|
@ -18,8 +18,8 @@ using Tegra::Engines::Maxwell3D;
|
||||||
|
|
||||||
std::string GetCommonDeclarations();
|
std::string GetCommonDeclarations();
|
||||||
|
|
||||||
boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
||||||
Maxwell3D::Regs::ShaderStage stage,
|
Maxwell3D::Regs::ShaderStage stage,
|
||||||
const std::string& suffix);
|
const std::string& suffix);
|
||||||
|
|
||||||
} // namespace OpenGL::GLShader::Decompiler
|
} // namespace OpenGL::GLShader::Decompiler
|
||||||
|
|
|
@ -37,7 +37,7 @@ layout(std140) uniform vs_config {
|
||||||
ProgramResult program =
|
ProgramResult program =
|
||||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||||
Maxwell3D::Regs::ShaderStage::Vertex, "vertex")
|
Maxwell3D::Regs::ShaderStage::Vertex, "vertex")
|
||||||
.get_value_or({});
|
.value_or(ProgramResult());
|
||||||
|
|
||||||
out += program.first;
|
out += program.first;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ layout(std140) uniform vs_config {
|
||||||
ProgramResult program_b =
|
ProgramResult program_b =
|
||||||
Decompiler::DecompileProgram(setup.program.code_b, PROGRAM_OFFSET,
|
Decompiler::DecompileProgram(setup.program.code_b, PROGRAM_OFFSET,
|
||||||
Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b")
|
Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b")
|
||||||
.get_value_or({});
|
.value_or(ProgramResult());
|
||||||
out += program_b.first;
|
out += program_b.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
|
||||||
ProgramResult program =
|
ProgramResult program =
|
||||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||||
Maxwell3D::Regs::ShaderStage::Geometry, "geometry")
|
Maxwell3D::Regs::ShaderStage::Geometry, "geometry")
|
||||||
.get_value_or({});
|
.value_or(ProgramResult());
|
||||||
out += R"(
|
out += R"(
|
||||||
out gl_PerVertex {
|
out gl_PerVertex {
|
||||||
vec4 gl_Position;
|
vec4 gl_Position;
|
||||||
|
@ -124,7 +124,7 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
|
||||||
ProgramResult program =
|
ProgramResult program =
|
||||||
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
Decompiler::DecompileProgram(setup.program.code, PROGRAM_OFFSET,
|
||||||
Maxwell3D::Regs::ShaderStage::Fragment, "fragment")
|
Maxwell3D::Regs::ShaderStage::Fragment, "fragment")
|
||||||
.get_value_or({});
|
.value_or(ProgramResult());
|
||||||
out += R"(
|
out += R"(
|
||||||
layout(location = 0) out vec4 FragColor0;
|
layout(location = 0) out vec4 FragColor0;
|
||||||
layout(location = 1) out vec4 FragColor1;
|
layout(location = 1) out vec4 FragColor1;
|
||||||
|
|
|
@ -115,7 +115,8 @@ RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window)
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
|
||||||
/// Swap buffers (render frame)
|
/// Swap buffers (render frame)
|
||||||
void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) {
|
void RendererOpenGL::SwapBuffers(
|
||||||
|
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) {
|
||||||
ScopeAcquireGLContext acquire_context{render_window};
|
ScopeAcquireGLContext acquire_context{render_window};
|
||||||
|
|
||||||
Core::System::GetInstance().GetPerfStats().EndSystemFrame();
|
Core::System::GetInstance().GetPerfStats().EndSystemFrame();
|
||||||
|
@ -124,11 +125,11 @@ void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&
|
||||||
OpenGLState prev_state = OpenGLState::GetCurState();
|
OpenGLState prev_state = OpenGLState::GetCurState();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
if (framebuffer != boost::none) {
|
if (framebuffer) {
|
||||||
// If framebuffer is provided, reload it from memory to a texture
|
// If framebuffer is provided, reload it from memory to a texture
|
||||||
if (screen_info.texture.width != (GLsizei)framebuffer->width ||
|
if (screen_info.texture.width != (GLsizei)framebuffer->get().width ||
|
||||||
screen_info.texture.height != (GLsizei)framebuffer->height ||
|
screen_info.texture.height != (GLsizei)framebuffer->get().height ||
|
||||||
screen_info.texture.pixel_format != framebuffer->pixel_format) {
|
screen_info.texture.pixel_format != framebuffer->get().pixel_format) {
|
||||||
// Reallocate texture if the framebuffer size has changed.
|
// Reallocate texture if the framebuffer size has changed.
|
||||||
// This is expected to not happen very often and hence should not be a
|
// This is expected to not happen very often and hence should not be a
|
||||||
// performance problem.
|
// performance problem.
|
||||||
|
|
|
@ -51,7 +51,8 @@ public:
|
||||||
~RendererOpenGL() override;
|
~RendererOpenGL() override;
|
||||||
|
|
||||||
/// Swap buffers (render frame)
|
/// Swap buffers (render frame)
|
||||||
void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) override;
|
void SwapBuffers(
|
||||||
|
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override;
|
||||||
|
|
||||||
/// Initialize the renderer
|
/// Initialize the renderer
|
||||||
bool Init() override;
|
bool Init() override;
|
||||||
|
|
|
@ -322,7 +322,7 @@ void ConfigureInput::setPollingResult(const Common::ParamPackage& params, bool a
|
||||||
}
|
}
|
||||||
|
|
||||||
updateButtonLabels();
|
updateButtonLabels();
|
||||||
input_setter = boost::none;
|
input_setter = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
void ConfigureInput::keyPressEvent(QKeyEvent* event) {
|
||||||
|
|
|
@ -7,11 +7,13 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "input_common/main.h"
|
#include "input_common/main.h"
|
||||||
|
@ -41,7 +43,7 @@ private:
|
||||||
std::unique_ptr<QTimer> poll_timer;
|
std::unique_ptr<QTimer> poll_timer;
|
||||||
|
|
||||||
/// This will be the the setting function when an input is awaiting configuration.
|
/// This will be the the setting function when an input is awaiting configuration.
|
||||||
boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
|
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
|
||||||
|
|
||||||
std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
|
std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
|
||||||
std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
|
std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
|
||||||
|
|
|
@ -173,7 +173,7 @@ void ConfigureSystem::UpdateCurrentUser() {
|
||||||
ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS);
|
ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS);
|
||||||
|
|
||||||
const auto& current_user = profile_manager->GetUser(Settings::values.current_user);
|
const auto& current_user = profile_manager->GetUser(Settings::values.current_user);
|
||||||
ASSERT(current_user != std::nullopt);
|
ASSERT(current_user);
|
||||||
const auto username = GetAccountUsername(*profile_manager, *current_user);
|
const auto username = GetAccountUsername(*profile_manager, *current_user);
|
||||||
|
|
||||||
scene->clear();
|
scene->clear();
|
||||||
|
@ -261,7 +261,7 @@ void ConfigureSystem::AddUser() {
|
||||||
void ConfigureSystem::RenameUser() {
|
void ConfigureSystem::RenameUser() {
|
||||||
const auto user = tree_view->currentIndex().row();
|
const auto user = tree_view->currentIndex().row();
|
||||||
const auto uuid = profile_manager->GetUser(user);
|
const auto uuid = profile_manager->GetUser(user);
|
||||||
ASSERT(uuid != std::nullopt);
|
ASSERT(uuid);
|
||||||
|
|
||||||
Service::Account::ProfileBase profile;
|
Service::Account::ProfileBase profile;
|
||||||
if (!profile_manager->GetProfileBase(*uuid, profile))
|
if (!profile_manager->GetProfileBase(*uuid, profile))
|
||||||
|
@ -297,7 +297,7 @@ void ConfigureSystem::RenameUser() {
|
||||||
void ConfigureSystem::DeleteUser() {
|
void ConfigureSystem::DeleteUser() {
|
||||||
const auto index = tree_view->currentIndex().row();
|
const auto index = tree_view->currentIndex().row();
|
||||||
const auto uuid = profile_manager->GetUser(index);
|
const auto uuid = profile_manager->GetUser(index);
|
||||||
ASSERT(uuid != std::nullopt);
|
ASSERT(uuid);
|
||||||
const auto username = GetAccountUsername(*profile_manager, *uuid);
|
const auto username = GetAccountUsername(*profile_manager, *uuid);
|
||||||
|
|
||||||
const auto confirm = QMessageBox::question(
|
const auto confirm = QMessageBox::question(
|
||||||
|
@ -324,7 +324,7 @@ void ConfigureSystem::DeleteUser() {
|
||||||
void ConfigureSystem::SetUserImage() {
|
void ConfigureSystem::SetUserImage() {
|
||||||
const auto index = tree_view->currentIndex().row();
|
const auto index = tree_view->currentIndex().row();
|
||||||
const auto uuid = profile_manager->GetUser(index);
|
const auto uuid = profile_manager->GetUser(index);
|
||||||
ASSERT(uuid != std::nullopt);
|
ASSERT(uuid);
|
||||||
|
|
||||||
const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(),
|
const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(),
|
||||||
tr("JPEG Images (*.jpg *.jpeg)"));
|
tr("JPEG Images (*.jpg *.jpeg)"));
|
||||||
|
|
|
@ -382,7 +382,7 @@ void GraphicsSurfaceWidget::OnUpdate() {
|
||||||
// TODO: Implement a good way to visualize alpha components!
|
// TODO: Implement a good way to visualize alpha components!
|
||||||
|
|
||||||
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
|
QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
|
||||||
boost::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
|
std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
|
||||||
|
|
||||||
// TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
|
// TODO(bunnei): Will not work with BCn formats that swizzle 4x4 tiles.
|
||||||
// Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
|
// Needs to be fixed if we plan to use this feature more, otherwise we may remove it.
|
||||||
|
@ -444,7 +444,7 @@ void GraphicsSurfaceWidget::SaveSurface() {
|
||||||
pixmap->save(&file, "PNG");
|
pixmap->save(&file, "PNG");
|
||||||
} else if (selectedFilter == bin_filter) {
|
} else if (selectedFilter == bin_filter) {
|
||||||
auto& gpu = Core::System::GetInstance().GPU();
|
auto& gpu = Core::System::GetInstance().GPU();
|
||||||
boost::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
|
std::optional<VAddr> address = gpu.MemoryManager().GpuToCpuAddress(surface_address);
|
||||||
|
|
||||||
const u8* buffer = Memory::GetPointer(*address);
|
const u8* buffer = Memory::GetPointer(*address);
|
||||||
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
|
ASSERT_MSG(buffer != nullptr, "Memory not accessible");
|
||||||
|
|
|
@ -786,7 +786,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
|
||||||
ASSERT(index != -1 && index < 8);
|
ASSERT(index != -1 && index < 8);
|
||||||
|
|
||||||
const auto user_id = manager.GetUser(index);
|
const auto user_id = manager.GetUser(index);
|
||||||
ASSERT(user_id != std::nullopt);
|
ASSERT(user_id);
|
||||||
path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser,
|
path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser,
|
||||||
FileSys::SaveDataType::SaveData,
|
FileSys::SaveDataType::SaveData,
|
||||||
program_id, user_id->uuid, 0);
|
program_id, user_id->uuid, 0);
|
||||||
|
@ -1560,7 +1560,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<u64> GMainWindow::SelectRomFSDumpTarget(
|
std::optional<u64> GMainWindow::SelectRomFSDumpTarget(
|
||||||
const FileSys::RegisteredCacheUnion& installed, u64 program_id) {
|
const FileSys::RegisteredCacheUnion& installed, u64 program_id) {
|
||||||
const auto dlc_entries =
|
const auto dlc_entries =
|
||||||
installed.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
|
installed.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
|
||||||
|
@ -1587,7 +1587,7 @@ boost::optional<u64> GMainWindow::SelectRomFSDumpTarget(
|
||||||
this, tr("Select RomFS Dump Target"),
|
this, tr("Select RomFS Dump Target"),
|
||||||
tr("Please select which RomFS you would like to dump."), list, 0, false, &ok);
|
tr("Please select which RomFS you would like to dump."), list, 0, false, &ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return boost::none;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return romfs_tids[list.indexOf(res)];
|
return romfs_tids[list.indexOf(res)];
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "ui_main.h"
|
#include "ui_main.h"
|
||||||
|
@ -178,8 +178,7 @@ private slots:
|
||||||
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<u64> SelectRomFSDumpTarget(const FileSys::RegisteredCacheUnion&,
|
std::optional<u64> SelectRomFSDumpTarget(const FileSys::RegisteredCacheUnion&, u64 program_id);
|
||||||
u64 program_id);
|
|
||||||
void UpdateStatusBar();
|
void UpdateStatusBar();
|
||||||
|
|
||||||
Ui::MainWindow ui;
|
Ui::MainWindow ui;
|
||||||
|
|
Loading…
Reference in New Issue