Implement read_from_ptr<>() util

Doing std::bit_cast on a "span".
Should be usable in constexpr.
This commit is contained in:
Nekotekina 2022-11-24 19:42:15 +03:00 committed by Ivan
parent bf388e5428
commit 7c15001042
9 changed files with 71 additions and 38 deletions

View file

@ -1698,7 +1698,7 @@ error_code cellDiscGameGetBootDiscInfo(vm::ptr<CellDiscGameSystemFileParam> getP
}
// Always sets 0 at first dword
*utils::bless<nse_t<u32, 1>>(getParam->titleId + 0) = 0;
write_to_ptr<u32>(getParam->titleId, 0);
// This is also called by non-disc games, see NPUB90029
static const std::string dir = "/dev_bdvd/PS3_GAME"s;

View file

@ -296,8 +296,8 @@ error_code cellGifDecReadHeader(vm::ptr<GifDecoder> mainHandle, vm::ptr<GifStrea
default: break; // TODO
}
if (*utils::bless<be_t<u32>>(buffer + 0) != 0x47494638u ||
(*utils::bless<le_t<u16>>(buffer + 4) != 0x6139u && *utils::bless<le_t<u16>>(buffer + 4) != 0x6137u)) // Error: The first 6 bytes are not a valid GIF signature
if (read_from_ptr<be_t<u32>>(buffer + 0) != 0x47494638u ||
(read_from_ptr<le_t<u16>>(buffer + 4) != 0x6139u && read_from_ptr<le_t<u16>>(buffer + 4) != 0x6137u)) // Error: The first 6 bytes are not a valid GIF signature
{
return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss
}

View file

@ -150,8 +150,8 @@ error_code cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr<CellJpgDe
default: break; // TODO
}
if (*utils::bless<le_t<u32>>(buffer.get() + 0) != 0xE0FFD8FF || // Error: Not a valid SOI header
*utils::bless<u32>(buffer.get() + 6) != "JFIF"_u32) // Error: Not a valid JFIF string
if (read_from_ptr<le_t<u32>>(buffer.get() + 0) != 0xE0FFD8FF || // Error: Not a valid SOI header
read_from_ptr<u32>(buffer.get() + 6) != "JFIF"_u32) // Error: Not a valid JFIF string
{
return CELL_JPGDEC_ERROR_HEADER;
}

View file

@ -92,10 +92,10 @@ void sky_portal::get_status(u8* reply_buf)
}
std::memset(reply_buf, 0, 0x20);
reply_buf[0] = 0x53;
*utils::bless<le_t<u16>>(reply_buf + 1) = status;
reply_buf[5] = interrupt_counter++;
reply_buf[6] = 0x01;
reply_buf[0] = 0x53;
write_to_ptr<le_t<u16>>(reply_buf, 1, status);
reply_buf[5] = interrupt_counter++;
reply_buf[6] = 0x01;
}
void sky_portal::query_block(u8 sky_num, u8 block, u8* reply_buf)
@ -159,7 +159,7 @@ u8 sky_portal::load_skylander(u8* buf, fs::file in_file)
{
std::lock_guard lock(sky_mutex);
u32 sky_serial = *utils::bless<le_t<u32>>(buf);
u32 sky_serial = read_from_ptr<le_t<u32>>(buf);
u8 found_slot = 0xFF;
// mimics spot retaining on the portal

View file

@ -192,9 +192,9 @@ namespace np
}
ticket_data tdata{};
const auto* ptr = data() + index;
tdata.id = *reinterpret_cast<const be_t<u16>*>(ptr);
tdata.len = *reinterpret_cast<const be_t<u16>*>(ptr + 2);
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;
auto check_size = [&](std::size_t expected) -> bool
@ -219,7 +219,7 @@ namespace np
{
return std::nullopt;
}
tdata.data.data_u32 = *reinterpret_cast<const be_t<u32>*>(data_ptr);
tdata.data.data_u32 = read_from_ptr<be_t<u32>>(data_ptr);
break;
case 2:
case 7:
@ -227,7 +227,7 @@ namespace np
{
return std::nullopt;
}
tdata.data.data_u64 = *reinterpret_cast<const be_t<u64>*>(data_ptr);
tdata.data.data_u64 = read_from_ptr<be_t<u64>>(data_ptr);
break;
case 4:
case 8:
@ -277,14 +277,14 @@ namespace np
return;
}
version = *reinterpret_cast<const be_t<u32>*>(data());
version = read_from_ptr<be_t<u32>>(data());
if (version != 0x21010000)
{
ticket_log.error("Invalid version: 0x%08x", version);
return;
}
u32 given_size = *reinterpret_cast<const be_t<u32>*>(data() + 4);
u32 given_size = read_from_ptr<be_t<u32>>(data() + 4);
if ((given_size + 8) != size())
{
ticket_log.error("Size mismatch (gs: %d vs s: %d)", given_size, size());
@ -471,7 +471,7 @@ namespace np
return;
}
local_ip_addr = *reinterpret_cast<u32*>(host->h_addr_list[0]);
local_ip_addr = read_from_ptr<u32>(host->h_addr_list[0]);
// Set public address to local discovered address for now, may be updated later from RPCN socket
public_ip_addr = local_ip_addr;

View file

@ -206,10 +206,10 @@ namespace np
return;
}
const u64 room_id = reinterpret_cast<le_t<u64>&>(data[0]);
const u16 member_id = reinterpret_cast<le_t<u16>&>(data[8]);
const u16 port_p2p = reinterpret_cast<be_t<u16>&>(data[10]);
const u32 addr_p2p = reinterpret_cast<le_t<u32>&>(data[12]);
const u64 room_id = read_from_ptr<le_t<u64>>(data);
const u16 member_id = read_from_ptr<le_t<u16>>(data, 8);
const u16 port_p2p = read_from_ptr<be_t<u16>>(data, 10);
const u32 addr_p2p = read_from_ptr<le_t<u32>>(data, 12);
rpcn_log.notice("Received notification to connect to member(%d) of room(%d): %s:%d", member_id, room_id, ip_to_string(addr_p2p), port_p2p);

View file

@ -705,8 +705,7 @@ namespace rsx
std::vector<u8> marker(range.length() + sizeof(overrun_cookie_value), 0);
// Tag end
u32* overrun_test_ptr = utils::bless<u32>(marker.data() + range.length());
*overrun_test_ptr = overrun_cookie_value;
write_to_ptr(marker, range.length(), overrun_cookie_value);
u32 removed_count = 0;
@ -717,10 +716,10 @@ namespace rsx
while (length >= 8)
{
auto& value = *utils::bless<u64>(dst_ptr);
const u64 value = read_from_ptr<u64>(dst_ptr);
const u64 block_mask = ~value; // If the value is not all 1s, set valid to true
mask |= block_mask;
value = umax;
write_to_ptr<u64>(dst_ptr, umax);
dst_ptr += 8;
length -= 8;
@ -728,10 +727,10 @@ namespace rsx
if (length >= 4)
{
auto& value = *utils::bless<u32>(dst_ptr);
const u32 value = read_from_ptr<u32>(dst_ptr);
const u32 block_mask = ~value;
mask |= block_mask;
value = umax;
write_to_ptr<u32>(dst_ptr, umax);
dst_ptr += 4;
length -= 4;
@ -739,10 +738,10 @@ namespace rsx
if (length >= 2)
{
auto& value = *utils::bless<u16>(dst_ptr);
const u16 value = read_from_ptr<u16>(dst_ptr);
const u16 block_mask = ~value;
mask |= block_mask;
value = umax;
write_to_ptr<u16>(dst_ptr, umax);
dst_ptr += 2;
length -= 2;
@ -750,10 +749,10 @@ namespace rsx
if (length)
{
auto& value = *dst_ptr;
const u8 value = *dst_ptr;
const u8 block_mask = ~value;
mask |= block_mask;
value = umax;
*dst_ptr = umax;
}
return !!mask;
@ -824,7 +823,7 @@ namespace rsx
rsx_log.notice("rsx::surface_cache::check_for_duplicates_fallback analysed %u overlapping sections and removed %u", ::size32(sections), removed_count);
// Verify no OOB
ensure(*overrun_test_ptr == overrun_cookie_value);
ensure(read_from_ptr<u32>(marker, range.length()) == overrun_cookie_value);
}
protected:

View file

@ -468,14 +468,14 @@ void ds3_pad_handler::get_extended_info(const pad_ensemble& binding)
#ifdef _WIN32
// Official Sony Windows DS3 driver seems to do the same modification of this value as the ps3
pad->m_sensors[0].m_value = *utils::bless<le_t<u16, 1>>(&ds3dev->padData[41 + DS3_HID_OFFSET]);
pad->m_sensors[0].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 41 + DS3_HID_OFFSET);
#else
// When getting raw values from the device this adjustement is needed
pad->m_sensors[0].m_value = 512 - (*utils::bless<le_t<u16, 1>>(&ds3dev->padData[41]) - 512);
pad->m_sensors[0].m_value = 512 - (read_from_ptr<le_t<u16>>(ds3dev->padData, 41 + DS3_HID_OFFSET) - 512);
#endif
pad->m_sensors[1].m_value = *utils::bless<le_t<u16, 1>>(&ds3dev->padData[45 + DS3_HID_OFFSET]);
pad->m_sensors[2].m_value = *utils::bless<le_t<u16, 1>>(&ds3dev->padData[43 + DS3_HID_OFFSET]);
pad->m_sensors[3].m_value = *utils::bless<le_t<u16, 1>>(&ds3dev->padData[47 + DS3_HID_OFFSET]);
pad->m_sensors[1].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 45 + DS3_HID_OFFSET);
pad->m_sensors[2].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 43 + DS3_HID_OFFSET);
pad->m_sensors[3].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 47 + DS3_HID_OFFSET);
// Those are formulas used to adjust sensor values in sys_hid code but I couldn't find all the vars.
//auto polish_value = [](s32 value, s32 dword_0x0, s32 dword_0x4, s32 dword_0x8, s32 dword_0xC, s32 dword_0x18, s32 dword_0x1C) -> u16

View file

@ -1184,6 +1184,40 @@ namespace stx
};
}
// Read object of type T from raw pointer, array, string, vector, or any contiguous container
template <typename T, typename U>
constexpr T read_from_ptr(U&& array, usz pos = 0)
{
// TODO: ensure array element types are trivial
static_assert(sizeof(T) % sizeof(array[0]) == 0);
std::decay_t<decltype(array[0])> buf[sizeof(T) / sizeof(array[0])];
if (!std::is_constant_evaluated())
std::memcpy(+buf, &array[pos], sizeof(buf));
else
for (usz i = 0; i < pos; buf[i] = array[pos + i], i++);
return std::bit_cast<T>(buf);
}
template <typename T, typename U>
constexpr void write_to_ptr(U&& array, usz pos, const T& value)
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
if (!std::is_constant_evaluated())
std::memcpy(&array[pos], &value, sizeof(value));
else
ensure(!"Unimplemented");
}
template <typename T, typename U>
constexpr void write_to_ptr(U&& array, const T& value)
{
static_assert(sizeof(T) % sizeof(array[0]) == 0);
if (!std::is_constant_evaluated())
std::memcpy(&array[0], &value, sizeof(value));
else
ensure(!"Unimplemented");
}
namespace utils
{
struct serial;