Move unsafe raw pointer write_to_ptr and read_from_ptr to write_to_ptr_unsafe and read_from_ptr_unsafe

This commit is contained in:
Megamouse 2026-06-30 23:41:24 +02:00
parent 88f81381e8
commit 773e4de3ca
26 changed files with 262 additions and 257 deletions

View File

@ -1432,8 +1432,8 @@ usz package_reader::decrypt(u64 offset, u64 size, const uchar* key, void* local_
sha1(reinterpret_cast<const u8*>(input), sizeof(input), hash.data);
const u128 v = read_from_ptr<u128>(out_data, i * 16);
write_to_ptr<u128>(out_data, i * 16, v ^ read_from_ptr<u128>(hash.data));
const u128 v = read_from_ptr_unsafe<u128>(out_data, i * 16);
write_to_ptr_unsafe<u128>(out_data, i * 16, v ^ read_from_ptr<u128>(hash.data));
}
}
else if (m_header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
@ -1453,8 +1453,8 @@ usz package_reader::decrypt(u64 offset, u64 size, const uchar* key, void* local_
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const u8*>(&input), reinterpret_cast<u8*>(&key));
const u128 v = read_from_ptr<u128>(out_data, i * 16);
write_to_ptr<u128>(out_data, i * 16, v ^ key);
const u128 v = read_from_ptr_unsafe<u128>(out_data, i * 16);
write_to_ptr_unsafe<u128>(out_data, i * 16, v ^ key);
}
}
else

View File

@ -332,12 +332,14 @@ void supplemental_header::Show() const
}
}
void MetadataInfo::Load(u8* in)
void MetadataInfo::Load(std::span<u8> in)
{
memcpy(key, in, 0x10);
memcpy(key_pad, in + 0x10, 0x10);
memcpy(iv, in + 0x20, 0x10);
memcpy(iv_pad, in + 0x30, 0x10);
ensure(in.size() >= sizeof(MetadataInfo));
std::memcpy(key, in.data(), 0x10);
std::memcpy(key_pad, in.data() + 0x10, 0x10);
std::memcpy(iv, in.data() + 0x20, 0x10);
std::memcpy(iv_pad, in.data() + 0x30, 0x10);
}
void MetadataInfo::Show() const
@ -360,10 +362,10 @@ void MetadataInfo::Show() const
self_log.notice("IV pad: %s", iv_pad_str.c_str());
}
void MetadataHeader::Load(u8* in)
void MetadataHeader::Load(std::span<u8> in)
{
// Endian swap.
signature_input_length = read_from_ptr<be_t<u64>>(in);
signature_input_length = read_from_ptr<be_t<u64>>(in, 0);
unknown1 = read_from_ptr<be_t<u32>>(in, 8);
section_count = read_from_ptr<be_t<u32>>(in, 12);
key_count = read_from_ptr<be_t<u32>>(in, 16);
@ -383,10 +385,10 @@ void MetadataHeader::Show() const
self_log.notice("Unknown3: 0x%08x", unknown3);
}
void MetadataSectionHeader::Load(u8* in)
void MetadataSectionHeader::Load(std::span<u8> in)
{
// Endian swap.
data_offset = read_from_ptr<be_t<u64>>(in);
data_offset = read_from_ptr<be_t<u64>>(in, 0);
data_size = read_from_ptr<be_t<u64>>(in, 8);
type = read_from_ptr<be_t<u32>>(in, 16);
program_idx = read_from_ptr<be_t<u32>>(in, 20);
@ -602,7 +604,6 @@ void ext_hdr::Load(const fs::file& f)
SCEDecrypter::SCEDecrypter(const fs::file& s)
: sce_f(s)
, data_buf_length(0)
{
}
@ -625,34 +626,33 @@ bool SCEDecrypter::LoadHeaders()
bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
{
aes_context aes;
const auto metadata_info = std::make_unique<u8[]>(sizeof(meta_info));
const auto metadata_headers_size = sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info));
const auto metadata_headers = std::make_unique<u8[]>(metadata_headers_size);
std::vector<u8> metadata_info(sizeof(meta_info));
std::vector<u8> metadata_headers(sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info)));
// Locate and read the encrypted metadata info.
sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr));
sce_f.read(metadata_info.get(), sizeof(meta_info));
sce_f.read(metadata_info.data(), metadata_info.size());
// Locate and read the encrypted metadata header and section header.
sce_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + sizeof(meta_info));
sce_f.read(metadata_headers.get(), metadata_headers_size);
sce_f.read(metadata_headers.data(), metadata_headers.size());
// Copy the necessary parameters.
u8 metadata_key[0x20];
u8 metadata_iv[0x10];
memcpy(metadata_key, erk, 0x20);
memcpy(metadata_iv, riv, 0x10);
std::memcpy(metadata_key, erk, 0x20);
std::memcpy(metadata_iv, riv, 0x10);
// Check DEBUG flag.
if ((sce_hdr.se_flags & 0x8000) != 0x8000)
{
// Decrypt the metadata info.
aes_setkey_dec(&aes, metadata_key, 256); // AES-256
aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get());
aes_crypt_cbc(&aes, AES_DECRYPT, metadata_info.size(), metadata_iv, metadata_info.data(), metadata_info.data());
}
// Load the metadata info.
meta_info.Load(metadata_info.get());
meta_info.Load(metadata_info);
// If the padding is not NULL for the key or iv fields, the metadata info
// is not properly decrypted.
@ -667,23 +667,28 @@ bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
aes_setkey_enc(&aes, meta_info.key, 128);
aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get());
aes_crypt_ctr(&aes, metadata_headers.size(), &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.data(), metadata_headers.data());
// Load the metadata header.
meta_hdr.Load(metadata_headers.get());
meta_hdr.Load(metadata_headers);
// Load the metadata section headers.
meta_shdr.clear();
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
const usz shdr_offset = sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i;
ensure(metadata_headers.size() > shdr_offset);
meta_shdr.emplace_back();
meta_shdr.back().Load(metadata_headers.get() + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i);
meta_shdr.back().Load(std::span<u8>(metadata_headers.data() + shdr_offset, metadata_headers.size() - shdr_offset));
}
// Copy the decrypted data keys.
data_keys_length = meta_hdr.key_count * 0x10;
data_keys = std::make_unique<u8[]>(data_keys_length);
memcpy(data_keys.get(), metadata_headers.get() + sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader), data_keys_length);
data_keys.resize(meta_hdr.key_count * 0x10);
const usz data_keys_offset = sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader);
ensure(metadata_headers.size() >= (data_keys_offset + data_keys.size()));
std::memcpy(data_keys.data(), metadata_headers.data() + data_keys_offset, data_keys.size());
return true;
}
@ -691,6 +696,7 @@ bool SCEDecrypter::LoadMetadata(const u8 erk[32], const u8 riv[16])
bool SCEDecrypter::DecryptData()
{
aes_context aes;
usz data_buf_length = 0;
// Calculate the total data size.
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
@ -699,7 +705,7 @@ bool SCEDecrypter::DecryptData()
}
// Allocate a buffer to store decrypted data.
data_buf = std::make_unique<u8[]>(data_buf_length);
data_buf.resize(data_buf_length);
// Set initial offset.
u32 data_buf_offset = 0;
@ -719,8 +725,8 @@ bool SCEDecrypter::DecryptData()
if ((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
{
// Get the key and iv from the previously stored key buffer.
memcpy(data_key, data_keys.get() + meta_shdr[i].key_idx * 0x10, 0x10);
memcpy(data_iv, data_keys.get() + meta_shdr[i].iv_idx * 0x10, 0x10);
std::memcpy(data_key, data_keys.data() + meta_shdr[i].key_idx * 0x10, 0x10);
std::memcpy(data_iv, data_keys.data() + meta_shdr[i].iv_idx * 0x10, 0x10);
// Allocate a buffer to hold the data.
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
@ -730,14 +736,14 @@ bool SCEDecrypter::DecryptData()
sce_f.read(buf.get(), meta_shdr[i].data_size);
// Zero out our ctr nonce.
memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
std::memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
// Perform AES-CTR encryption on the data blocks.
aes_setkey_enc(&aes, data_key, 128);
aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
// Copy the decrypted data.
memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
}
}
else
@ -745,7 +751,7 @@ bool SCEDecrypter::DecryptData()
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
sce_f.seek(meta_shdr[i].data_offset);
sce_f.read(buf.get(), meta_shdr[i].data_size);
memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
}
// Advance the buffer's offset.
@ -767,7 +773,7 @@ std::vector<fs::file> SCEDecrypter::MakeFile()
for (u32 i = 0; i < meta_hdr.section_count; i++)
{
const MetadataSectionHeader& hdr = meta_shdr[i];
const u8* src = data_buf.get() + data_buf_offset;
const u8* src = data_buf.data() + data_buf_offset;
fs::file out_f = fs::make_stream<std::vector<u8>>();
bool is_valid = true;
@ -1071,7 +1077,7 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
aes_crypt_ecb(&aes, AES_DECRYPT, npdrm_key, npdrm_key);
// IV is empty.
memset(npdrm_iv, 0, 0x10);
std::memset(npdrm_iv, 0, 0x10);
// Use our final key to decrypt the NPDRM layer.
aes_setkey_dec(&aes, npdrm_key, 128);
@ -1097,20 +1103,19 @@ const NPD_HEADER* SELFDecrypter::GetNPDHeader() const
bool SELFDecrypter::LoadMetadata(const u8* klic_key)
{
aes_context aes;
const auto metadata_info = std::make_unique<u8[]>(sizeof(meta_info));
const auto metadata_headers_size = sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info));
const auto metadata_headers = std::make_unique<u8[]>(metadata_headers_size);
std::vector<u8> metadata_info(sizeof(meta_info));
std::vector<u8> metadata_headers(sce_hdr.se_hsize - (sizeof(sce_hdr) + sce_hdr.se_meta + sizeof(meta_info)));
// Locate and read the encrypted metadata info.
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr));
self_f.read(metadata_info.get(), sizeof(meta_info));
self_f.read(metadata_info.data(), metadata_info.size());
// Locate and read the encrypted metadata header and section header.
self_f.seek(sce_hdr.se_meta + sizeof(sce_hdr) + sizeof(meta_info));
self_f.read(metadata_headers.get(), metadata_headers_size);
self_f.read(metadata_headers.data(), metadata_headers.size());
// Find the right keyset from the key vault.
SELF_KEY keyset = key_v.FindSelfKey(m_prog_id_hdr.program_type, sce_hdr.se_flags, m_prog_id_hdr.program_sceversion);
const SELF_KEY keyset = key_v.FindSelfKey(m_prog_id_hdr.program_type, sce_hdr.se_flags, m_prog_id_hdr.program_sceversion);
// Set klic if given
if (klic_key)
@ -1126,16 +1131,16 @@ bool SELFDecrypter::LoadMetadata(const u8* klic_key)
if ((sce_hdr.se_flags & 0x8000) != 0x8000)
{
// Decrypt the NPDRM layer.
if (!DecryptNPDRM(metadata_info.get(), sizeof(meta_info)))
if (!DecryptNPDRM(metadata_info.data(), ::size32(metadata_info)))
return false;
// Decrypt the metadata info.
aes_setkey_dec(&aes, metadata_key, 256); // AES-256
aes_crypt_cbc(&aes, AES_DECRYPT, sizeof(meta_info), metadata_iv, metadata_info.get(), metadata_info.get());
aes_crypt_cbc(&aes, AES_DECRYPT, metadata_info.size(), metadata_iv, metadata_info.data(), metadata_info.data());
}
// Load the metadata info.
meta_info.Load(metadata_info.get());
meta_info.Load(metadata_info);
// If the padding is not NULL for the key or iv fields, the metadata info
// is not properly decrypted.
@ -1150,23 +1155,28 @@ bool SELFDecrypter::LoadMetadata(const u8* klic_key)
usz ctr_nc_off = 0;
u8 ctr_stream_block[0x10];
aes_setkey_enc(&aes, meta_info.key, 128);
aes_crypt_ctr(&aes, metadata_headers_size, &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.get(), metadata_headers.get());
aes_crypt_ctr(&aes, metadata_headers.size(), &ctr_nc_off, meta_info.iv, ctr_stream_block, metadata_headers.data(), metadata_headers.data());
// Load the metadata header.
meta_hdr.Load(metadata_headers.get());
meta_hdr.Load(metadata_headers);
// Load the metadata section headers.
meta_shdr.clear();
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
{
const usz shdr_offset = sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i;
ensure(metadata_headers.size() > shdr_offset);
meta_shdr.emplace_back();
meta_shdr.back().Load(metadata_headers.get() + sizeof(meta_hdr) + sizeof(MetadataSectionHeader) * i);
meta_shdr.back().Load(std::span<u8>(metadata_headers.data() + shdr_offset, metadata_headers.size() - shdr_offset));
}
// Copy the decrypted data keys.
data_keys_length = meta_hdr.key_count * 0x10;
data_keys = std::make_unique<u8[]>(data_keys_length);
memcpy(data_keys.get(), metadata_headers.get() + sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader), data_keys_length);
data_keys.resize(meta_hdr.key_count * 0x10);
const usz data_keys_offset = sizeof(meta_hdr) + meta_hdr.section_count * sizeof(MetadataSectionHeader);
ensure(metadata_headers.size() >= (data_keys_offset + data_keys.size()));
std::memcpy(data_keys.data(), metadata_headers.data() + data_keys_offset, data_keys.size());
return true;
}
@ -1174,6 +1184,7 @@ bool SELFDecrypter::LoadMetadata(const u8* klic_key)
bool SELFDecrypter::DecryptData()
{
aes_context aes;
usz data_buf_length = 0;
// Calculate the total data size.
for (unsigned int i = 0; i < meta_hdr.section_count; i++)
@ -1186,7 +1197,7 @@ bool SELFDecrypter::DecryptData()
}
// Allocate a buffer to store decrypted data.
data_buf = std::make_unique<u8[]>(data_buf_length);
data_buf.resize(data_buf_length);
// Set initial offset.
u32 data_buf_offset = 0;
@ -1206,8 +1217,8 @@ bool SELFDecrypter::DecryptData()
if((meta_shdr[i].key_idx <= meta_hdr.key_count - 1) && (meta_shdr[i].iv_idx <= meta_hdr.key_count))
{
// Get the key and iv from the previously stored key buffer.
memcpy(data_key, data_keys.get() + meta_shdr[i].key_idx * 0x10, 0x10);
memcpy(data_iv, data_keys.get() + meta_shdr[i].iv_idx * 0x10, 0x10);
std::memcpy(data_key, data_keys.data() + meta_shdr[i].key_idx * 0x10, 0x10);
std::memcpy(data_iv, data_keys.data() + meta_shdr[i].iv_idx * 0x10, 0x10);
// Allocate a buffer to hold the data.
auto buf = std::make_unique<u8[]>(meta_shdr[i].data_size);
@ -1217,14 +1228,14 @@ bool SELFDecrypter::DecryptData()
self_f.read(buf.get(), meta_shdr[i].data_size);
// Zero out our ctr nonce.
memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
std::memset(ctr_stream_block, 0, sizeof(ctr_stream_block));
// Perform AES-CTR encryption on the data blocks.
aes_setkey_enc(&aes, data_key, 128);
aes_crypt_ctr(&aes, meta_shdr[i].data_size, &ctr_nc_off, data_iv, ctr_stream_block, buf.get(), buf.get());
// Copy the decrypted data.
memcpy(data_buf.get() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
std::memcpy(data_buf.data() + data_buf_offset, buf.get(), meta_shdr[i].data_size);
// Advance the buffer's offset.
data_buf_offset += ::narrow<u32>(meta_shdr[i].data_size);
@ -1255,8 +1266,7 @@ fs::file SELFDecrypter::MakeElf(bool isElf32)
bool SELFDecrypter::GetKeyFromRap(const char* content_id, u8* npdrm_key)
{
// Set empty RAP key.
u8 rap_key[0x10];
memset(rap_key, 0, 0x10);
std::array<u8, 0x10> rap_key {};
// Try to find a matching RAP file under exdata folder.
const std::string ci_str = content_id;
@ -1275,14 +1285,14 @@ bool SELFDecrypter::GetKeyFromRap(const char* content_id, u8* npdrm_key)
self_log.notice("Loading RAP file %s.rap", ci_str);
if (rap_file.read(rap_key, 0x10) != 0x10)
if (rap_file.read(rap_key.data(), rap_key.size()) != rap_key.size())
{
self_log.fatal("Failed to load %s: RAP file exists but is invalid. Try reinstalling it.", rap_path);
return false;
}
// Convert the RAP key.
rap_to_rif(rap_key, npdrm_key);
rap_to_rif(rap_key.data(), npdrm_key);
return true;
}
@ -1480,7 +1490,7 @@ bool verify_npdrm_self_headers(const fs::file& self, u8* klic_key, NPD_HEADER* n
{
if (const NPD_HEADER* npd = self_dec.GetNPDHeader())
{
memcpy(npd_out, npd, sizeof(NPD_HEADER));
std::memcpy(npd_out, npd, sizeof(NPD_HEADER));
}
}
}
@ -1512,7 +1522,7 @@ bool get_npdrm_self_header(const fs::file& self, NPD_HEADER &npd_out)
if (const NPD_HEADER* npd = self_dec.GetNPDHeader())
{
memcpy(&npd_out, npd, sizeof(NPD_HEADER));
std::memcpy(&npd_out, npd, sizeof(NPD_HEADER));
return true;
}
}

View File

@ -9,6 +9,8 @@
#include "unedat.h"
#include <span>
LOG_CHANNEL(self_log, "SELF");
// SCE-specific definitions for e_type:
@ -163,7 +165,7 @@ struct MetadataInfo
u8 iv[0x10];
u8 iv_pad[0x10];
void Load(u8* in);
void Load(std::span<u8> in);
void Show() const;
};
@ -177,7 +179,7 @@ struct MetadataHeader
u32 unknown2;
u32 unknown3;
void Load(u8* in);
void Load(std::span<u8> in);
void Show() const;
};
@ -194,7 +196,7 @@ struct MetadataSectionHeader
u32 iv_idx;
u32 compressed;
void Load(u8* in);
void Load(std::span<u8> in);
void Show() const;
};
@ -416,13 +418,11 @@ protected:
// Metadata structs.
MetadataInfo meta_info{};
MetadataHeader meta_hdr{};
std::vector<MetadataSectionHeader> meta_shdr{};
std::vector<MetadataSectionHeader> meta_shdr;
// Internal data buffers.
std::unique_ptr<u8[]> data_keys{};
u32 data_keys_length{};
std::unique_ptr<u8[]> data_buf{};
u32 data_buf_length{};
std::vector<u8> data_keys;
std::vector<u8> data_buf;
public:
SCEDecrypter(const fs::file& s);
@ -463,10 +463,8 @@ class SELFDecrypter
std::vector<MetadataSectionHeader> meta_shdr{};
// Internal data buffers.
std::unique_ptr<u8[]> data_keys{};
u32 data_keys_length{};
std::unique_ptr<u8[]> data_buf{};
u32 data_buf_length{};
std::vector<u8> data_keys;
std::vector<u8> data_buf;
// Main key vault instance.
KeyVault key_v{};
@ -512,14 +510,13 @@ private:
std::unique_ptr<u8[]> decomp_buf(new u8[filesz]);
// Create a buffer separate from data_buf to uncompress.
std::unique_ptr<u8[]> zlib_buf(new u8[data_buf_length]);
memcpy(zlib_buf.get(), data_buf.get(), data_buf_length);
std::vector<u8> zlib_buf = data_buf;
uLongf decomp_buf_length = ::narrow<uLongf>(filesz);
// Use zlib uncompress on the new buffer.
// decomp_buf_length changes inside the call to uncompress
const int rv = uncompress(decomp_buf.get(), &decomp_buf_length, zlib_buf.get() + data_buf_offset, data_buf_length);
const int rv = uncompress(decomp_buf.get(), &decomp_buf_length, zlib_buf.data() + data_buf_offset, ::size32(zlib_buf));
// Check for errors (TODO: Probably safe to remove this once these changes have passed testing.)
switch (rv)
@ -538,7 +535,7 @@ private:
{
// Seek to the program header data offset and write the data.
e.seek(phdr[meta_shdr[i].program_idx].p_offset);
e.write(data_buf.get() + data_buf_offset, meta_shdr[i].data_size);
e.write(data_buf.data() + data_buf_offset, meta_shdr[i].data_size);
}
// Advance the data buffer offset by data size.

View File

@ -482,7 +482,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
case CELL_ADEC_CH_3_2_LFE:
for (s32 i = 0; i < sample_num; i += channel_num)
{
const u64 tmp = std::rotl(read_from_ptr<u64>(&_output[i + 1]), 0x20); // Swap Front Right and Center
const u64 tmp = std::rotl(read_from_ptr_unsafe<u64>(_output, i + 1), 0x20); // Swap Front Right and Center
std::memcpy(&_output[i + 1], &tmp, sizeof(u64));
}
break;
@ -511,7 +511,7 @@ void LpcmDecContext::exec(ppu_thread& ppu)
{
const v128 tmp1 = gv_shuffle32<3, 2, 0, 1>(v128::loadu(&_output[i + 4])); // Reorder Rear Left, Rear Right, Side Right, LFE -> LFE, Side Right, Rear Left, Rear Right
v128::storeu(tmp1, &_output[i + 4]);
const u64 tmp2 = std::rotl(read_from_ptr<u64>(&_output[i + 3]), 0x20); // Swap Side Left and LFE
const u64 tmp2 = std::rotl(read_from_ptr_unsafe<u64>(_output, i + 3), 0x20); // Swap Side Left and LFE
std::memcpy(&_output[i + 3], &tmp2, sizeof(u64));
}
break;
@ -620,8 +620,8 @@ void LpcmDecContext::exec(ppu_thread& ppu)
const v128 tmp1 = gv_loadu32(&input_u8[i_in]);
const v128 tmp2 = gv_loadu32(&input_u8[i_in + high_bytes_3_4_offset]);
v128 s20be = gv_unpacklo32(tmp1, tmp2);
s20be = gv_insert16<4>(s20be, read_from_ptr<u16>(&input_u8[i_in + low_bits_1_2_offset]));
s20be = gv_insert16<5>(s20be, read_from_ptr<u16>(&input_u8[i_in + low_bits_3_4_offset]));
s20be = gv_insert16<4>(s20be, read_from_ptr_unsafe<u16>(input_u8, i_in + low_bits_1_2_offset));
s20be = gv_insert16<5>(s20be, read_from_ptr_unsafe<u16>(input_u8, i_in + low_bits_3_4_offset));
// Reorder bytes to form four 32-bit integer samples
v128 _s32 = gv_shuffle8(s20be, shuffle_ctrl);
@ -651,8 +651,8 @@ void LpcmDecContext::exec(ppu_thread& ppu)
const v128 tmp1 = gv_loadu32(&input_u8[i_in]);
const v128 tmp2 = gv_loadu32(&input_u8[i_in + high_bytes_3_4_offset]);
v128 s24be = gv_unpacklo32(tmp1, tmp2);
s24be = gv_insert16<4>(s24be, read_from_ptr<u16>(&input_u8[i_in + low_bytes_1_2_offset]));
s24be = gv_insert16<5>(s24be, read_from_ptr<u16>(&input_u8[i_in + low_bytes_3_4_offset]));
s24be = gv_insert16<4>(s24be, read_from_ptr_unsafe<u16>(input_u8, i_in + low_bytes_1_2_offset));
s24be = gv_insert16<5>(s24be, read_from_ptr_unsafe<u16>(input_u8, i_in + low_bytes_3_4_offset));
// Reorder bytes to form four 32-bit integer samples
const v128 _s32 = std::endian::native == std::endian::little

View File

@ -773,7 +773,7 @@ error_code _CellAdecCoreOpOpenExt_atracx(ppu_thread& ppu, vm::ptr<AtracXdecConte
ensure(handle.aligned(0x80)); // On LLE, this functions doesn't check the alignment or aligns the address itself. The address should already be aligned to 128 bytes by cellAdec
ensure(!!notifyAuDone && !!notifyAuDoneArg && !!notifyPcmOut && !!notifyPcmOutArg && !!notifyError && !!notifyErrorArg && !!notifySeqDone && !!notifySeqDoneArg); // These should always be set by cellAdec
write_to_ptr(handle.get_ptr(), AtracXdecContext(notifyAuDone, notifyAuDoneArg, notifyPcmOut, notifyPcmOutArg, notifyError, notifyErrorArg, notifySeqDone, notifySeqDoneArg,
write_to_ptr_unsafe(handle.get_ptr(), AtracXdecContext(notifyAuDone, notifyAuDoneArg, notifyPcmOut, notifyPcmOutArg, notifyError, notifyErrorArg, notifySeqDone, notifySeqDoneArg,
vm::bptr<u8>::make(handle.addr() + utils::align(static_cast<u32>(sizeof(AtracXdecContext)), 0x80) + ATXDEC_SPURS_STRUCTS_SIZE)));
const vm::var<sys_mutex_attribute_t> mutex_attr{{ SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, SYS_SYNC_NOT_PROCESS_SHARED, SYS_SYNC_NOT_ADAPTIVE, 0, 0, 0, { "_atd001"_u64 } }};

View File

@ -309,7 +309,7 @@ u32 dmux_pamf_base::video_stream<avc>::parse_stream(std::span<const u8> stream)
// Search for delimiter in cache
for (; cache_idx < static_cast<s32>(cache.size()); cache_idx++)
{
if (const be_t<u32> code = read_from_ptr<be_t<u32>>(buf.data(), cache_idx);
if (const be_t<u32> code = read_from_ptr<be_t<u32>>(buf, cache_idx);
(avc && code == AVC_AU_DELIMITER) || (!avc && (code == M2V_PIC_START || code == M2V_SEQUENCE_HEADER || code == M2V_SEQUENCE_END)))
{
if (current_au.state != access_unit::state::none && (avc || current_au.state != access_unit::state::m2v_sequence))
@ -335,7 +335,7 @@ u32 dmux_pamf_base::video_stream<avc>::parse_stream(std::span<const u8> stream)
// Search for delimiter in stream
for (; stream_it <= stream.end() - sizeof(u32); stream_it++)
{
if (const be_t<u32> code = read_from_ptr<be_t<u32>>(stream_it);
if (const be_t<u32> code = read_from_ptr_unsafe<be_t<u32>>(stream_it);
(avc && code == AVC_AU_DELIMITER) || (!avc && (code == M2V_PIC_START || code == M2V_SEQUENCE_HEADER || code == M2V_SEQUENCE_END)))
{
if (current_au.state != access_unit::state::none && (avc || current_au.state != access_unit::state::m2v_sequence))
@ -440,7 +440,7 @@ u32 dmux_pamf_base::audio_stream<ac3>::parse_stream(std::span<const u8> stream)
// Search for delimiter in cache
for (; cache_idx <= static_cast<s32>(cache.size() + std::min(sizeof(u16) - 1, stream.size()) - sizeof(u16)); cache_idx++)
{
if (const be_t<u16> tmp = read_from_ptr<be_t<u16>>(buf.data(), cache_idx); current_au.size_info_offset != 0)
if (const be_t<u16> tmp = read_from_ptr<be_t<u16>>(buf, cache_idx); current_au.size_info_offset != 0)
{
if (--current_au.size_info_offset == 0)
{
@ -473,7 +473,7 @@ u32 dmux_pamf_base::audio_stream<ac3>::parse_stream(std::span<const u8> stream)
// Search for delimiter in stream
for (; stream_it <= stream.end() - sizeof(u32); stream_it++) // LLE uses sizeof(u32), even though the delimiter is only two bytes large
{
if (const be_t<u16> tmp = read_from_ptr<be_t<u16>>(stream_it); current_au.size_info_offset != 0)
if (const be_t<u16> tmp = read_from_ptr_unsafe<be_t<u16>>(stream_it); current_au.size_info_offset != 0)
{
if (--current_au.size_info_offset == 0)
{
@ -524,7 +524,7 @@ u32 dmux_pamf_base::user_data_stream::parse_stream_header(std::span<const u8> pe
return umax;
}
au_size_unk = read_from_ptr<be_t<u32>>(pes_packet_data.begin(), 2) - sizeof(u32);
au_size_unk = read_from_ptr<be_t<u32>>(pes_packet_data, 2) - sizeof(u32);
return 10;
}
@ -741,7 +741,7 @@ bool dmux_pamf_base::process_next_pack()
// Skip over system header if present
if (read_from_ptr<be_t<u32>>(current_pes_packet) == SYSTEM_HEADER)
{
const u32 system_header_length = read_from_ptr<be_t<u16>>(current_pes_packet.begin(), PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
const u32 system_header_length = read_from_ptr<be_t<u16>>(current_pes_packet, PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
// Not checked on LLE, the SPU task would just increment the reading position and read random data in the SPU local store
if (system_header_length + PES_HEADER_DATA_LENGTH_OFFSET + sizeof(u8) > current_pes_packet.size())
@ -766,7 +766,7 @@ bool dmux_pamf_base::process_next_pack()
// A system header is optionally followed by a private stream 2
// The first two bytes of the stream are the stream id of a video stream. The next access unit of that stream is a random access point/keyframe
const u16 pes_packet_length = read_from_ptr<be_t<u16>>(current_pes_packet.begin(), PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
const u16 pes_packet_length = read_from_ptr<be_t<u16>>(current_pes_packet, PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
// Not checked on LLE, the SPU task would just increment the reading position and read random data in the SPU local store
if (pes_packet_length + PES_HEADER_DATA_LENGTH_OFFSET + sizeof(u8) > current_pes_packet.size())
@ -775,7 +775,7 @@ bool dmux_pamf_base::process_next_pack()
return false;
}
if (const u8 channel = read_from_ptr<be_t<u16>>(current_pes_packet.begin(), PES_PACKET_LENGTH_OFFSET + sizeof(u16)) & 0xf;
if (const u8 channel = read_from_ptr<be_t<u16>>(current_pes_packet, PES_PACKET_LENGTH_OFFSET + sizeof(u16)) & 0xf;
elementary_stream::is_enabled(elementary_streams[0][channel]))
{
elementary_streams[0][channel]->set_rap();
@ -796,8 +796,8 @@ bool dmux_pamf_base::process_next_pack()
return false;
}
const u16 pes_packet_length = read_from_ptr<be_t<u16>>(current_pes_packet.begin(), PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
const u8 pes_header_data_length = read_from_ptr<u8>(current_pes_packet.begin(), PES_HEADER_DATA_LENGTH_OFFSET) + PES_HEADER_DATA_LENGTH_OFFSET + sizeof(u8);
const u16 pes_packet_length = read_from_ptr<be_t<u16>>(current_pes_packet, PES_PACKET_LENGTH_OFFSET) + PES_PACKET_LENGTH_OFFSET + sizeof(u16);
const u8 pes_header_data_length = read_from_ptr<u8>(current_pes_packet, PES_HEADER_DATA_LENGTH_OFFSET) + PES_HEADER_DATA_LENGTH_OFFSET + sizeof(u8);
// Not checked on LLE, the SPU task would just increment the reading position and read random data in the SPU local store
if (pes_packet_length > current_pes_packet.size() || pes_packet_length <= pes_header_data_length)
@ -821,23 +821,23 @@ bool dmux_pamf_base::process_next_pack()
if (elementary_stream::is_enabled(elementary_streams[type_idx][channel]))
{
const s8 pts_dts_flag = read_from_ptr<s8>(current_pes_packet.begin(), PTS_DTS_FLAG_OFFSET);
const s8 pts_dts_flag = read_from_ptr<s8>(current_pes_packet, PTS_DTS_FLAG_OFFSET);
if (pts_dts_flag < 0)
{
// The timestamps should be unsigned, but are sign-extended from s32 to u64 on LLE. They probably forgot about integer promotion
const s32 PTS_32_30 = read_from_ptr<bf_t<u8, 1, 7>>(current_pes_packet.begin(), 9);
const s32 PTS_29_15 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet.begin(), 10);
const s32 PTS_14_0 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet.begin(), 12);
const s32 PTS_32_30 = read_from_ptr<bf_t<u8, 1, 7>>(current_pes_packet, 9);
const s32 PTS_29_15 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet, 10);
const s32 PTS_14_0 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet, 12);
elementary_streams[type_idx][channel]->set_pts(PTS_32_30 << 30 | PTS_29_15 << 15 | PTS_14_0); // Bit 32 is discarded
}
if (pts_dts_flag & 0x40)
{
const s32 DTS_32_30 = read_from_ptr<bf_t<u8, 1, 7>>(current_pes_packet.begin(), 14);
const s32 DTS_29_15 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet.begin(), 15);
const s32 DTS_14_0 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet.begin(), 17);
const s32 DTS_32_30 = read_from_ptr<bf_t<u8, 1, 7>>(current_pes_packet, 14);
const s32 DTS_29_15 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet, 15);
const s32 DTS_14_0 = read_from_ptr<bf_t<be_t<u16>, 1, 15>>(current_pes_packet, 17);
elementary_streams[type_idx][channel]->set_dts(DTS_32_30 << 30 | DTS_29_15 << 15 | DTS_14_0); // Bit 32 is discarded
}

View File

@ -366,7 +366,7 @@ template <CellSysmoduleModuleID module_id>
const vm::var<std::byte[]> boot_flag(8);
std::memset(boot_flag.get_ptr(), 0, boot_flag.get_count());
if (ret != CELL_OK || !read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
if (ret != CELL_OK || !read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
{
const vm::var<u32> file_descriptor;
@ -379,15 +379,15 @@ template <CellSysmoduleModuleID module_id>
ensure(sys_fs_read(ppu, *file_descriptor, boot_flag, 8, nread) == CELL_OK && *nread == 8ull); // Not checked on LLE
ensure(sys_fs_close(ppu, *file_descriptor) == CELL_OK); // Not checked on LLE
return !!read_from_ptr<bf_t<u64, 4, 1>>(boot_flag.get_ptr(), 1);
return !!read_from_ptr_unsafe<bf_t<u64, 4, 1>>(boot_flag.get_ptr(), 1);
}
return !read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x10);
return !read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x10);
}
case CELL_SYSMODULE_GCM_SYS:
{
// If the extra load flag "EnableGCMDebug" is set, loads libgcm_sys_deh.sprx instead of libgcm_sys.sprx
return ret != CELL_OK || !read_from_ptr<bf_t<u64, 2, 1>>(paramsfo.get_ptr(), 0x10);
return ret != CELL_OK || !read_from_ptr_unsafe<bf_t<u64, 2, 1>>(paramsfo.get_ptr(), 0x10);
}
case CELL_SYSMODULE_FS:
{
@ -579,7 +579,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
{
if (module_id == CELL_SYSMODULE_GCM_SYS)
{
if (get_paramsfo_ret == CELL_OK && read_from_ptr<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys)
if (get_paramsfo_ret == CELL_OK && read_from_ptr_unsafe<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys)
{
if (load_module(ppu, GCM_SYS_DEH_IDX, 8, paramsfo + 0x28) != CELL_OK)
{
@ -641,7 +641,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
// Start the modules
for (const auto [module_id, prx_ix] : std::views::zip(DEFAULT_MODULES, std::span{ id_list.begin().get_ptr(), id_list.get_count() }))
{
if (module_id == CELL_SYSMODULE_GCM_SYS && read_from_ptr<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys)
if (module_id == CELL_SYSMODULE_GCM_SYS && read_from_ptr_unsafe<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys)
{
s_sysmodule_context->module_states[CELL_SYSMODULE_GCM_SYS].prx_id = static_cast<s32>(prx_ix);
@ -691,7 +691,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
// Load additional modules if certain ExtraLoadFlags are set
if (read_from_ptr<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys && read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
if (read_from_ptr_unsafe<bf_t<u64, 6, 1>>(paramsfo.get_ptr(), 0x10) && !retail_gcm_sys && read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
{
cellSysmoduleSetDebugmode(true);
@ -703,7 +703,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
cellSysmoduleSetDebugmode(false);
}
if (read_from_ptr<bf_t<u64, 3, 1>>(paramsfo.get_ptr(), 0x10) && read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
if (read_from_ptr_unsafe<bf_t<u64, 3, 1>>(paramsfo.get_ptr(), 0x10) && read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18))
{
if (load_module(ppu, PROF_IDX, 0, vm::null) != CELL_OK)
{
@ -711,7 +711,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
}
}
if (read_from_ptr<bf_t<u64, 4, 1>>(paramsfo.get_ptr(), 0x10))
if (read_from_ptr_unsafe<bf_t<u64, 4, 1>>(paramsfo.get_ptr(), 0x10))
{
if (load_module(ppu, LV2COREDUMP_IDX, 0, vm::null) != CELL_OK)
{
@ -719,7 +719,7 @@ extern error_code sysmoduleModuleStart(ppu_thread& ppu, u32 args, vm::ptr<void>
}
}
if (read_from_ptr<bf_t<u64, 1, 1>>(paramsfo.get_ptr(), 0x10))
if (read_from_ptr_unsafe<bf_t<u64, 1, 1>>(paramsfo.get_ptr(), 0x10))
{
if (cellSysmoduleLoadModuleInternal(ppu, 0xf022) != CELL_OK)
{
@ -1152,7 +1152,7 @@ error_code cellSysmoduleLoadModuleInternal(ppu_thread& ppu, u16 id)
std::memset(paramsfo.get_ptr(), 0, paramsfo.get_count());
if (ppu_execute<&sys_process_get_paramsfo>(ppu, +paramsfo) != CELL_OK
|| (!read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18) && !read_from_ptr<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x30)))
|| (!read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x18) && !read_from_ptr_unsafe<bf_t<u64, 0, 1>>(paramsfo.get_ptr(), 0x30)))
{
return CELL_SYSMODULE_ERROR_UNKNOWN;
}

View File

@ -480,7 +480,7 @@ static inline u8* ppu_seg_ptr(u32 addr)
static inline ppu_intrp_func_t ppu_read(u32 addr)
{
return read_from_ptr<ppu_intrp_func_t>(ppu_ptr(addr));
return read_from_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr));
}
// Get interpreter cache value
@ -505,7 +505,7 @@ static void ppu_fallback(ppu_thread& ppu, ppu_opcode_t op, be_t<u32>* this_op, p
{
const auto _pc = vm::get_addr(this_op);
const auto _fn = ppu_cache(_pc);
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(_pc), _fn);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(_pc), _fn);
return _fn(ppu, op, this_op, next_fn);
}
@ -590,7 +590,7 @@ u32 ppu_read_mmio_aware_u32(u8* vm_base, u32 eal)
}
// Value is assumed to be swapped
return read_from_ptr<u32>(vm_base, eal);
return read_from_ptr_unsafe<u32>(vm_base, eal);
}
void ppu_write_mmio_aware_u32(u8* vm_base, u32 eal, u32 value)
@ -618,7 +618,7 @@ void ppu_write_mmio_aware_u32(u8* vm_base, u32 eal, u32 value)
}
// Value is assumed swapped
write_to_ptr<u32>(vm_base + eal, value);
write_to_ptr_unsafe<u32>(vm_base + eal, value);
}
extern bool ppu_test_address_may_be_mmio(std::span<const be_t<u32>> insts)
@ -793,13 +793,13 @@ extern void ppu_register_range(u32 addr, u32 size)
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
{
// Assume addr is the start of first segment of PRX
write_to_ptr<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ppu_recompiler_fallback_ghc));
write_to_ptr<u16>(ppu_seg_ptr(addr), static_cast<u16>(seg_base >> 13));
write_to_ptr_unsafe<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ppu_recompiler_fallback_ghc));
write_to_ptr_unsafe<u16>(ppu_seg_ptr(addr), static_cast<u16>(seg_base >> 13));
}
else
{
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), ppu_fallback);
write_to_ptr<u16>(ppu_seg_ptr(addr), 0);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), ppu_fallback);
write_to_ptr_unsafe<u16>(ppu_seg_ptr(addr), 0);
}
addr += 4;
@ -814,7 +814,7 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr =
// Initialize specific function
if (ptr)
{
write_to_ptr<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ptr));
write_to_ptr_unsafe<uptr>(ppu_ptr(addr), std::bit_cast<uptr>(ptr));
return;
}
@ -841,7 +841,7 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr =
{
if (auto old = ppu_read(addr); old != ppu_break && old != ppu_far_jump)
{
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), ppu_cache(addr));
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), ppu_cache(addr));
}
addr += 4;
@ -1270,7 +1270,7 @@ extern bool ppu_breakpoint(u32 addr, bool is_adding)
return false;
}
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), breakpoint);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), breakpoint);
return true;
}
@ -1279,7 +1279,7 @@ extern bool ppu_breakpoint(u32 addr, bool is_adding)
return false;
}
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), func_original);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), func_original);
return true;
}
@ -1314,7 +1314,7 @@ extern bool ppu_patch(u32 addr, u32 value)
{
if (auto old = ppu_read(addr); old != ppu_break && old != ppu_fallback)
{
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), ppu_cache(addr));
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), ppu_cache(addr));
}
}
@ -3979,7 +3979,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
if (auto klic_ptr = mod->get_ptr<const u8>(static_cast<u32>(constant_value), 16))
{
// Try to read from that address
if (const u128 klic_value = read_from_ptr<u128>(klic_ptr))
if (const u128 klic_value = read_from_ptr_unsafe<u128>(klic_ptr))
{
if (!std::count_if(decrypt_klics.begin(), decrypt_klics.end(), FN(std::memcmp(&x, &klic_value, 16) == 0)))
{
@ -4537,7 +4537,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
if (g_cfg.core.ppu_debug && func.size && func.toc != umax && !ppu_get_far_jump(func.addr))
{
ppu_toc[func.addr] = func.toc;
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(func.addr), &ppu_check_toc);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(func.addr), &ppu_check_toc);
}
}
@ -4736,7 +4736,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
[[maybe_unused]] auto write_le = [](u8*& code, auto value)
{
write_to_ptr<le_t<std::remove_cvref_t<decltype(value)>>>(code, value);
write_to_ptr_unsafe<le_t<std::remove_cvref_t<decltype(value)>>>(code, value);
code += sizeof(value);
};
@ -5559,7 +5559,7 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
{
if (*inst_ptr == ppu_instructions::BLR() && reinterpret_cast<uptr>(ppu_read(addr)) == reinterpret_cast<uptr>(ppu_recompiler_fallback_ghc))
{
write_to_ptr<ppu_intrp_func_t>(ppu_ptr(addr), BLR_func);
write_to_ptr_unsafe<ppu_intrp_func_t>(ppu_ptr(addr), BLR_func);
}
}
}

View File

@ -7235,7 +7235,7 @@ s64 spu_channel::pop_wait(cpu_thread& spu, bool pop)
while (true)
{
const usz is_le = std::endian::native == std::endian::little ? 1 : 0;
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(&data)[is_le], read_from_ptr<u32>(reinterpret_cast<char*>(&old), is_le * 4));
thread_ctrl::wait_on(utils::bless<atomic_t<u32>>(&data)[is_le], read_from_ptr_unsafe<u32>(reinterpret_cast<char*>(&old), is_le * 4));
old = data;

View File

@ -48,12 +48,12 @@ public:
return true;
}
bool write(u8* buffer)
bool write(const u8* buffer)
{
if (!buffer)
return false;
storage.store(read_from_ptr<be_t<v128>>(buffer));
storage.store(read_from_ptr_unsafe<be_t<v128>>(buffer));
written = true;
return true;

View File

@ -96,8 +96,8 @@ u32 dimensions_toypad::get_next()
std::array<u8, 8> dimensions_toypad::decrypt(const u8* buf, std::optional<std::array<u8, 16>> key)
{
// Value to decrypt is separated in to two little endian 32 bit unsigned integers
u32 data_one = read_from_ptr<le_t<u32>>(buf);
u32 data_two = read_from_ptr<le_t<u32>>(buf, 4);
u32 data_one = read_from_ptr_unsafe<le_t<u32>>(buf);
u32 data_two = read_from_ptr_unsafe<le_t<u32>>(buf, 4);
// Use the key as 4 32 bit little endian unsigned integers
u32 key_one;
@ -143,8 +143,8 @@ std::array<u8, 8> dimensions_toypad::encrypt(const u8* buf, std::optional<std::a
{
// Value to encrypt is separated in to two little endian 32 bit unsigned integers
u32 data_one = read_from_ptr<le_t<u32>>(buf);
u32 data_two = read_from_ptr<le_t<u32>>(buf, 4);
u32 data_one = read_from_ptr_unsafe<le_t<u32>>(buf);
u32 data_two = read_from_ptr_unsafe<le_t<u32>>(buf, 4);
// Use the key as 4 32 bit little endian unsigned integers
u32 key_one;
@ -328,7 +328,7 @@ void dimensions_toypad::write_block(u8 index, u8 page, const u8* to_write_buf, s
// Id is written to page 36
if (page == 36)
{
figure.id = read_from_ptr<le_t<u32>>(to_write_buf);
figure.id = read_from_ptr_unsafe<le_t<u32>>(to_write_buf);
}
std::memcpy(figure.data.data() + (page * 4), to_write_buf, 4);
figure.save();

View File

@ -91,7 +91,7 @@ void sky_portal::get_status(u8* reply_buf)
std::memset(reply_buf, 0, 0x20);
reply_buf[0] = 0x53;
write_to_ptr<le_t<u16>>(reply_buf, 1, status);
write_to_ptr_unsafe<le_t<u16>>(reply_buf, 1, status);
reply_buf[5] = interrupt_counter++;
reply_buf[6] = 0x01;
}
@ -153,11 +153,11 @@ bool sky_portal::remove_skylander(u8 sky_num)
return false;
}
u8 sky_portal::load_skylander(u8* buf, fs::file in_file)
u8 sky_portal::load_skylander(const std::array<u8, 0x40 * 0x10>& data, fs::file in_file)
{
std::lock_guard lock(sky_mutex);
const u32 sky_serial = read_from_ptr<le_t<u32>>(buf);
const u32 sky_serial = read_from_ptr<le_t<u32>>(data);
u8 found_slot = 0xFF;
// mimics spot retaining on the portal
@ -181,7 +181,7 @@ u8 sky_portal::load_skylander(u8* buf, fs::file in_file)
ensure(found_slot != 0xFF);
skylander& thesky = skylanders[found_slot];
memcpy(thesky.data.data(), buf, thesky.data.size());
memcpy(thesky.data.data(), data.data(), thesky.data.size());
thesky.sky_file = std::move(in_file);
thesky.status = 3;
thesky.queued_status.push(3);

View File

@ -2,6 +2,7 @@
#include "Emu/Io/usb_device.h"
#include "Utilities/mutex.h"
#include <array>
#include <queue>
struct skylander
@ -26,7 +27,7 @@ public:
void write_block(u8 sky_num, u8 block, const u8* to_write_buf, u8* reply_buf);
bool remove_skylander(u8 sky_num);
u8 load_skylander(u8* buf, fs::file in_file);
u8 load_skylander(const std::array<u8, 0x40 * 0x10>& data, fs::file in_file);
protected:
shared_mutex sky_mutex;

View File

@ -1700,8 +1700,8 @@ namespace vm
for (usz i = 0; i < byte_of_pages; i += 128 * 2)
{
const u64 sample64_1 = read_from_ptr<u64>(data_ptr, i);
const u64 sample64_2 = read_from_ptr<u64>(data_ptr, i + 128);
const u64 sample64_1 = read_from_ptr_unsafe<u64>(data_ptr, i);
const u64 sample64_2 = read_from_ptr_unsafe<u64>(data_ptr, i + 128);
// Speed up testing in scenarios where it is likely non-zero data
if (sample64_1 && sample64_2)

View File

@ -116,7 +116,7 @@ namespace np
parse();
}
std::size_t ticket::size() const
usz ticket::size() const
{
return raw_data.size();
}
@ -258,7 +258,7 @@ namespace np
return std::string(vec.begin(), it);
}
std::optional<ticket_data> ticket::parse_node(std::size_t index) const
std::optional<ticket_data> ticket::parse_node(usz index) const
{
if ((index + MIN_TICKET_DATA_SIZE) > size())
{
@ -268,11 +268,11 @@ namespace np
ticket_data tdata{};
const auto* ptr = data() + index;
tdata.id = read_from_ptr<be_t<u16>>(ptr);
tdata.len = read_from_ptr<be_t<u16>>(ptr + 2);
const auto* data_ptr = data() + index + 4;
tdata.id = read_from_ptr_unsafe<be_t<u16>>(ptr);
tdata.len = read_from_ptr_unsafe<be_t<u16>>(ptr, 2);
const usz data_offset = index + 4;
auto check_size = [&](std::size_t expected) -> bool
auto check_size = [&](usz expected) -> bool
{
if ((index + MIN_TICKET_DATA_SIZE + expected) > size())
{
@ -294,7 +294,7 @@ namespace np
{
return std::nullopt;
}
tdata.data.data_u32 = read_from_ptr<be_t<u32>>(data_ptr);
tdata.data.data_u32 = read_from_ptr_unsafe<be_t<u32>>(data(), data_offset);
break;
case 2:
case 7:
@ -302,7 +302,7 @@ namespace np
{
return std::nullopt;
}
tdata.data.data_u64 = read_from_ptr<be_t<u64>>(data_ptr);
tdata.data.data_u64 = read_from_ptr_unsafe<be_t<u64>>(data(), data_offset);
break;
case 4:
case 8:
@ -311,7 +311,7 @@ namespace np
return std::nullopt;
}
tdata.data.data_vec = std::vector<u8>(tdata.len);
memcpy(tdata.data.data_vec.data(), data_ptr, tdata.len);
memcpy(tdata.data.data_vec.data(), data() + data_offset, tdata.len);
break;
default:
if ((tdata.id & 0x3000) == 0x3000)
@ -321,7 +321,7 @@ namespace np
return std::nullopt;
}
std::size_t sub_index = 0;
usz sub_index = 0;
tdata.data.data_nodes = {};
while (sub_index < tdata.len)
{
@ -352,14 +352,14 @@ namespace np
return;
}
version = read_from_ptr<be_t<u32>>(data());
version = read_from_ptr_unsafe<be_t<u32>>(data());
if (version != 0x21010000)
{
ticket_log.error("Invalid version: 0x%08x", version);
return;
}
u32 given_size = read_from_ptr<be_t<u32>>(data(), 4);
u32 given_size = read_from_ptr_unsafe<be_t<u32>>(data(), 4);
if ((given_size + 8) != size())
{
ticket_log.error("Size mismatch (gs: %d vs s: %d)", given_size, size());

View File

@ -65,7 +65,7 @@ namespace np
ticket() = default;
ticket(std::vector<u8>&& raw_data);
std::size_t size() const;
usz size() const;
const u8* data() const;
bool empty() const;
@ -73,11 +73,11 @@ namespace np
std::string get_service_id() const;
private:
std::optional<ticket_data> parse_node(std::size_t index) const;
std::optional<ticket_data> parse_node(usz index) const;
void parse();
private:
static constexpr std::size_t MIN_TICKET_DATA_SIZE = 4;
static constexpr usz MIN_TICKET_DATA_SIZE = 4;
std::vector<u8> raw_data;

View File

@ -713,50 +713,49 @@ namespace rsx
u32 removed_count = 0;
auto compare_and_tag_row = [&](const u32 offset, u32 length) -> bool
auto compare_and_tag_row = [&](u32 offset, u32 length) -> bool
{
u64 mask = 0;
u8* dst_ptr = marker.data() + offset;
while (length >= 8)
{
const u64 value = read_from_ptr<u64>(dst_ptr);
const u64 value = read_from_ptr<u64>(marker, offset);
const u64 block_mask = ~value; // If the value is not all 1s, set valid to true
mask |= block_mask;
write_to_ptr<u64>(dst_ptr, umax);
write_to_ptr<u64>(marker, offset, umax);
dst_ptr += 8;
offset += 8;
length -= 8;
}
if (length >= 4)
{
const u32 value = read_from_ptr<u32>(dst_ptr);
const u32 value = read_from_ptr<u32>(marker, offset);
const u32 block_mask = ~value;
mask |= block_mask;
write_to_ptr<u32>(dst_ptr, umax);
write_to_ptr<u32>(marker, offset, umax);
dst_ptr += 4;
offset += 4;
length -= 4;
}
if (length >= 2)
{
const u16 value = read_from_ptr<u16>(dst_ptr);
const u16 value = read_from_ptr<u16>(marker, offset);
const u16 block_mask = ~value;
mask |= block_mask;
write_to_ptr<u16>(dst_ptr, umax);
write_to_ptr<u16>(marker, offset, umax);
dst_ptr += 2;
offset += 2;
length -= 2;
}
if (length)
{
const u8 value = *dst_ptr;
const u8 value = read_from_ptr<u8>(marker, offset);
const u8 block_mask = ~value;
mask |= block_mask;
*dst_ptr = umax;
write_to_ptr<u8>(marker, offset, umax);
}
return !!mask;

View File

@ -187,7 +187,7 @@ namespace rsx
const u64 src_op2_2 = read_from_ptr<be_t<u64>>(fifo_span, second_index_off);
// Fast comparison
if (src_op1_2 != read_from_ptr<u64>(out_ptr, first_index_off) || src_op2_2 != read_from_ptr<u64>(out_ptr, second_index_off))
if (src_op1_2 != read_from_ptr_unsafe<u64>(out_ptr, first_index_off) || src_op2_2 != read_from_ptr_unsafe<u64>(out_ptr, second_index_off))
{
to_set_dirty = rsx::pipeline_state::vertex_program_ucode_dirty;
}

View File

@ -202,7 +202,7 @@ namespace rsx
}
}
const auto ret = read_from_ptr<be_t<u32>>(+m_cache[0], addr - m_cache_addr);
const auto ret = read_from_ptr_unsafe<be_t<u32>>(+m_cache[0], addr - m_cache_addr);
return {true, ret};
}

View File

@ -393,13 +393,13 @@ namespace rsx
_max_index = 0;
auto re_evaluate = [&] <typename T> (const std::byte* ptr, T)
const auto re_evaluate = [&] <typename T> (const std::byte* ptr, T)
{
const u64 restart = rsx::method_registers.restart_index_enabled() ? rsx::method_registers.restart_index() : u64{umax};
for (u32 _index = first; _index < first + count; _index++)
{
const auto value = read_from_ptr<be_t<T>>(ptr, _index * sizeof(T));
const auto value = read_from_ptr_unsafe<be_t<T>>(ptr, _index * sizeof(T));
if (value == restart)
{

View File

@ -4013,7 +4013,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
continue;
}
const u64 hash_val = read_from_ptr<be_t<u64>>(result.data) & -65536;
const u64 hash_val = read_from_ptr_unsafe<be_t<u64>>(result.data) & -65536;
const f64 usage = get_cpu_program_usage_percent(hash_val);
if (usage == 0)

View File

@ -139,7 +139,7 @@ std::unique_ptr<utils::serial> tar_object::get_file(const std::string& path, std
}
else
{
tar_log.notice("tar_object::get_file() failed to parse header: offset=0x%x, filesize=0x%x, header_first16=0x%016x", offset, max_size, read_from_ptr<be_t<u128>>(reinterpret_cast<const u8*>(&header)));
tar_log.notice("tar_object::get_file() failed to parse header: offset=0x%x, filesize=0x%x, header_first16=0x%016x", offset, max_size, read_from_ptr_unsafe<be_t<u128>>(reinterpret_cast<const u8*>(&header)));
}
return { size, {} };

View File

@ -865,7 +865,7 @@ void memory_viewer_panel::ShowMemory()
if (const auto ptr = this->to_ptr(addr))
{
const be_t<u32> rmem = read_from_ptr<be_t<u32>>(static_cast<const u8*>(ptr));
const be_t<u32> rmem = read_from_ptr_unsafe<be_t<u32>>(static_cast<const u8*>(ptr));
t_mem_hex_str += QString::fromStdString(fmt::format("%02x %02x %02x %02x",
static_cast<u8>(rmem >> 24),
static_cast<u8>(rmem >> 16),

View File

@ -640,19 +640,18 @@ skylander_creator_dialog::skylander_creator_dialog(QWidget* parent)
}
std::array<u8, 0x40 * 0x10> buf{};
const auto data = buf.data();
// Set the block permissions
write_to_ptr<le_t<u32>>(data, 0x36, 0x690F0F0F);
write_to_ptr<le_t<u32>>(buf, 0x36, 0x690F0F0F);
for (u32 index = 1; index < 0x10; index++)
{
write_to_ptr<le_t<u32>>(data, (index * 0x40) + 0x36, 0x69080F7F);
write_to_ptr<le_t<u32>>(buf, (index * 0x40) + 0x36, 0x69080F7F);
}
// Set the skylander infos
write_to_ptr<le_t<u16>>(data, (sky_id | sky_var) + 1);
write_to_ptr<le_t<u16>>(data, 0x10, sky_id);
write_to_ptr<le_t<u16>>(data, 0x1C, sky_var);
write_to_ptr<le_t<u16>>(buf, (sky_id | sky_var) + 1);
write_to_ptr<le_t<u16>>(buf, 0x10, sky_id);
write_to_ptr<le_t<u16>>(buf, 0x1C, sky_var);
// Set checksum
write_to_ptr<le_t<u16>>(data, 0x1E, skylander_crc16(0xFFFF, data, 0x1E));
write_to_ptr<le_t<u16>>(buf, 0x1E, skylander_crc16(0xFFFF, buf.data(), 0x1E));
sky_file.write(buf.data(), buf.size());
sky_file.close();
@ -796,10 +795,10 @@ void skylander_dialog::load_skylander_path(u8 slot, const QString& path)
clear_skylander(slot);
u16 sky_id = reinterpret_cast<le_t<u16>&>(data[0x10]);
u16 sky_var = reinterpret_cast<le_t<u16>&>(data[0x1C]);
const u16 sky_id = reinterpret_cast<le_t<u16>&>(data[0x10]);
const u16 sky_var = reinterpret_cast<le_t<u16>&>(data[0x1C]);
u8 portal_slot = g_skyportal.load_skylander(data.data(), std::move(sky_file));
const u8 portal_slot = g_skyportal.load_skylander(data, std::move(sky_file));
sky_slots[slot] = std::tuple(portal_slot, sky_id, sky_var);
update_edits();

View File

@ -77,7 +77,6 @@ namespace utils
// write_to_ptr and read_from_ptr with pos
std::array<u32, sizeof(u128) / sizeof(u32)> arr32_2{};
std::memset(arr32_2.data(), 0, arr32_2.size() * sizeof(u32));
for (u32 i = 0; i < arr32_2.size() * sizeof(u32); i += sizeof(u32))
{
const usz index = i / sizeof(u32);
@ -86,7 +85,7 @@ namespace utils
EXPECT_EQ(read_from_ptr<u32>(arr32_2, index), i);
}
std::memset(arr32_2.data(), 0, arr32_2.size() * sizeof(u32));
arr32_2 = {};
for (u64 i = 0; i < arr32_2.size() * sizeof(u32); i += sizeof(u64))
{
const usz index = i / sizeof(u64);
@ -95,7 +94,7 @@ namespace utils
EXPECT_EQ(read_from_ptr<u64>(arr32_2, index), i);
}
std::memset(arr32_2.data(), 0, arr32_2.size() * sizeof(u32));
arr32_2 = {};
for (usz i = 0; i < arr32_2.size() * sizeof(u32); i += sizeof(u128))
{
const usz index = i / sizeof(u128);
@ -252,7 +251,7 @@ namespace utils
#endif
}
TEST(Utils, read_write_to_ptr_raw_array)
TEST(Utils, read_write_to_ptr_unsafe)
{
g_headless = true; // Disable exception popups
@ -261,13 +260,13 @@ namespace utils
u8* arr = new u8[arr_size];
std::memset(arr, 0, arr_size);
write_to_ptr(arr, u8(umax));
write_to_ptr_unsafe(arr, u8(umax));
EXPECT_EQ(*arr, u8(umax));
write_to_ptr(arr, u16(umax));
write_to_ptr_unsafe(arr, u16(umax));
EXPECT_EQ(*utils::bless<u16>(arr), u16(umax));
write_to_ptr(arr, u32(umax));
write_to_ptr_unsafe(arr, u32(umax));
EXPECT_EQ(*utils::bless<u32>(arr), u32(umax));
write_to_ptr(arr, u64(umax));
write_to_ptr_unsafe(arr, u64(umax));
EXPECT_EQ(*utils::bless<u64>(arr), u64(umax));
// write_to_ptr and read_from_ptr with pos
@ -277,42 +276,42 @@ namespace utils
std::memset(arr2, 0, arr2_size);
for (u8 i = 0; i < arr2_size; i++)
{
write_to_ptr(arr2, i, i);
write_to_ptr_unsafe(arr2, i, i);
EXPECT_EQ(arr2[i], i);
EXPECT_EQ(read_from_ptr<u8>(arr2, i), i);
EXPECT_EQ(read_from_ptr_unsafe<u8>(arr2, i), i);
}
std::memset(arr2, 0, arr2_size);
for (u16 i = 0; i < arr2_size; i += sizeof(u16))
{
write_to_ptr(arr2, i, i);
write_to_ptr_unsafe(arr2, i, i);
EXPECT_EQ(*utils::bless<u16>(arr2 + i), i);
EXPECT_EQ(read_from_ptr<u16>(arr2, i), i);
EXPECT_EQ(read_from_ptr_unsafe<u16>(arr2, i), i);
}
std::memset(arr2, 0, arr2_size);
for (u32 i = 0; i < arr2_size; i += sizeof(u32))
{
write_to_ptr(arr2, i, i);
write_to_ptr_unsafe(arr2, i, i);
EXPECT_EQ(*utils::bless<u32>(arr2 + i), i);
EXPECT_EQ(read_from_ptr<u32>(arr2, i), i);
EXPECT_EQ(read_from_ptr_unsafe<u32>(arr2, i), i);
}
std::memset(arr2, 0, arr2_size);
for (usz i = 0; i < arr2_size; i += sizeof(u64))
{
write_to_ptr(arr2, i, u64(i));
write_to_ptr_unsafe(arr2, i, u64(i));
EXPECT_EQ(*utils::bless<u64>(arr2 + i), i);
EXPECT_EQ(read_from_ptr<u64>(arr2, i), i);
EXPECT_EQ(read_from_ptr_unsafe<u64>(arr2, i), i);
}
std::memset(arr2, 0, arr2_size);
for (usz i = 0; i < arr2_size; i += sizeof(u128))
{
write_to_ptr(arr2, i, u128(i));
write_to_ptr_unsafe(arr2, i, u128(i));
const u128 exp_u128 = i;
EXPECT_EQ(std::memcmp(arr2, &exp_u128, sizeof(u128)), 0);
const u128 val_u128 = read_from_ptr<u128>(arr2, i);
const u128 val_u128 = read_from_ptr_unsafe<u128>(arr2, i);
EXPECT_EQ(std::memcmp(&val_u128, &exp_u128, sizeof(u128)), 0);
}
@ -322,9 +321,9 @@ namespace utils
u32* arr32 = new u32[arr32_count];
std::memset(arr32, 0, arr32_size);
write_to_ptr(arr32, u32(umax));
write_to_ptr_unsafe(arr32, u32(umax));
EXPECT_EQ(*utils::bless<u32>(arr32), u32(umax));
write_to_ptr(arr32, u64(umax));
write_to_ptr_unsafe(arr32, u64(umax));
EXPECT_EQ(*utils::bless<u64>(arr32), u64(umax));
// write_to_ptr and read_from_ptr with pos
@ -336,57 +335,31 @@ namespace utils
for (u32 i = 0; i < arr32_2_size; i += sizeof(u32))
{
const usz index = i / sizeof(u32);
write_to_ptr(arr32_2, index, i);
write_to_ptr_unsafe(arr32_2, index, i);
EXPECT_EQ(*utils::bless<u32>(arr32_2 + index), i);
EXPECT_EQ(read_from_ptr<u32>(arr32_2, index), i);
EXPECT_EQ(read_from_ptr_unsafe<u32>(arr32_2, index), i);
}
std::memset(arr32_2, 0, arr32_2_size);
for (u64 i = 0; i < arr32_2_size; i += sizeof(u64))
{
const usz index = i / sizeof(u64);
write_to_ptr(arr32_2, index, i);
write_to_ptr_unsafe(arr32_2, index, i);
EXPECT_EQ(*utils::bless<u64>(arr32_2 + index), i);
EXPECT_EQ(read_from_ptr<u64>(arr32_2, index), i);
EXPECT_EQ(read_from_ptr_unsafe<u64>(arr32_2, index), i);
}
std::memset(arr32_2, 0, arr32_2_size);
for (usz i = 0; i < arr32_2_size; i += sizeof(u128))
{
const usz index = i / sizeof(u128);
write_to_ptr(arr32_2, index, u128(i));
write_to_ptr_unsafe(arr32_2, index, u128(i));
const u128 exp_u128 = i;
EXPECT_EQ(std::memcmp(arr32_2, &exp_u128, sizeof(u128)), 0);
const u128 val_u128 = read_from_ptr<u128>(arr32_2, index);
const u128 val_u128 = read_from_ptr_unsafe<u128>(arr32_2, index);
EXPECT_EQ(std::memcmp(&val_u128, &exp_u128, sizeof(u128)), 0);
}
// There are no sanity checks for raw pointers in these functions, so these will not fail.
#if 0
// These tests can take a long time and produce warnings, so let's only run them in local builds
#if CHECK_DEATH
EXPECT_DEATH(write_to_ptr(arr, u128()), ".*");
EXPECT_DEATH(write_to_ptr(arr2, arr2_size, u8()), ".*");
EXPECT_DEATH(write_to_ptr(arr2, arr2_size, u16()), ".*");
EXPECT_DEATH(write_to_ptr(arr2, arr2_size, u32()), ".*");
EXPECT_DEATH(write_to_ptr(arr2, arr2_size, u64()), ".*");
EXPECT_DEATH(write_to_ptr(arr2, arr2_size, u128()), ".*");
EXPECT_DEATH(read_from_ptr<u8>(arr2, arr2_size), ".*");
EXPECT_DEATH(read_from_ptr<u16>(arr2, arr2_size), ".*");
EXPECT_DEATH(read_from_ptr<u32>(arr2, arr2_size), ".*");
EXPECT_DEATH(read_from_ptr<u64>(arr2, arr2_size), ".*");
EXPECT_DEATH(read_from_ptr<u128>(arr2, arr2_size), ".*");
EXPECT_DEATH(write_to_ptr(arr32, u128()), ".*");
EXPECT_DEATH(write_to_ptr(arr32_2, arr32_count, u32()), ".*");
EXPECT_DEATH(write_to_ptr(arr32_2, arr32_count, u64()), ".*");
EXPECT_DEATH(write_to_ptr(arr32_2, arr32_count, u128()), ".*");
EXPECT_DEATH(read_from_ptr<u32>(arr32_2, arr32_count), ".*");
EXPECT_DEATH(read_from_ptr<u64>(arr32_2, arr32_count), ".*");
EXPECT_DEATH(read_from_ptr<u128>(arr32_2, arr32_count), ".*");
#endif
#endif
delete[] arr;
delete[] arr2;
delete[] arr32;

View File

@ -1197,6 +1197,7 @@ namespace stx
// Read object of type T from raw pointer, array, string, vector, or any contiguous container
template <typename T, typename U>
requires requires(U&& array) { std::size(array); std::data(array); }
constexpr T read_from_ptr(U&& array, usz pos = 0, std::source_location src_loc = std::source_location::current())
{
// TODO: ensure array element types are trivial
@ -1207,10 +1208,7 @@ constexpr T read_from_ptr(U&& array, usz pos = 0, std::source_location src_loc =
if (!std::is_constant_evaluated())
{
if constexpr (requires { std::size(array); })
{
ensure((pos + elements_per_value) <= std::size(array), src_loc);
}
ensure((pos + elements_per_value) <= std::size(array), src_loc);
std::memcpy(+buf, &array[pos], sizeof(buf));
}
@ -1225,16 +1223,28 @@ constexpr T read_from_ptr(U&& array, usz pos = 0, std::source_location src_loc =
return std::bit_cast<T>(buf);
}
// Read object of type T from raw pointer, array, string, vector, or any contiguous container
template <typename T, typename U>
requires (!requires(U&& array) { std::size(array); std::data(array); })
constexpr T read_from_ptr_unsafe(U&& array, usz pos = 0)
{
// TODO: ensure array element types are trivial
static_assert(sizeof(T) % sizeof(array[0]) == 0);
constexpr usz elements_per_value = sizeof(T) / sizeof(array[0]);
std::decay_t<decltype(array[0])> buf[elements_per_value];
std::memcpy(+buf, &array[pos], sizeof(buf));
return std::bit_cast<T>(buf);
}
template <typename T, typename U>
requires requires(U&& array) { std::size(array); std::data(array); }
constexpr void write_to_ptr(U&& array, usz pos, const T& value, std::source_location src_loc = std::source_location::current())
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
constexpr usz elements_per_value = sizeof(T) / sizeof(array[0]);
if constexpr (requires { std::size(array); })
{
ensure((pos + elements_per_value) <= std::size(array), src_loc);
}
ensure((pos + elements_per_value) <= std::size(array), src_loc);
if (!std::is_constant_evaluated())
{
@ -1247,15 +1257,13 @@ constexpr void write_to_ptr(U&& array, usz pos, const T& value, std::source_loca
}
template <typename T, typename U>
requires requires(U&& array) { std::size(array); std::data(array); }
constexpr void write_to_ptr(U&& array, const T& value, std::source_location src_loc = std::source_location::current())
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
constexpr usz elements_per_value = sizeof(T) / sizeof(array[0]);
if constexpr (requires { std::size(array); })
{
ensure(elements_per_value <= std::size(array), src_loc);
}
ensure(elements_per_value <= std::size(array), src_loc);
if (!std::is_constant_evaluated())
{
@ -1267,6 +1275,24 @@ constexpr void write_to_ptr(U&& array, const T& value, std::source_location src_
}
}
template <typename T, typename U>
requires (!requires(U&& array) { std::size(array); std::data(array); })
constexpr void write_to_ptr_unsafe(U&& array, usz pos, const T& value)
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
std::memcpy(static_cast<void*>(&array[pos]), &value, sizeof(value));
}
template <typename T, typename U>
requires (!requires(U&& array) { std::size(array); std::data(array); })
constexpr void write_to_ptr_unsafe(U&& array, const T& value)
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
std::memcpy(static_cast<void*>(&array[0]), &value, sizeof(value));
}
constexpr struct aref_tag_t{} aref_tag{};
template <typename T, typename U>
@ -1288,12 +1314,12 @@ public:
constexpr T value() const
{
return read_from_ptr<T>(m_ptr);
return read_from_ptr_unsafe<T>(m_ptr);
}
constexpr operator T() const
{
return read_from_ptr<T>(m_ptr);
return read_from_ptr_unsafe<T>(m_ptr);
}
aref& operator=(const aref&) = delete;