Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility fixups #12977

Merged
merged 4 commits into from
Nov 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Utilities/StrFmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,18 +449,19 @@ struct fmt::cfmt_src
{
// Hack: use known function pointers to determine type
#define TYPE(type) \
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type);
if (sup[extra].fmt_string == &fmt_class_string<type>::format) return sizeof(type);

TYPE(int);
TYPE(llong);
TYPE(schar);
TYPE(short);
if (std::is_signed<char>::value) TYPE(char);
TYPE(long);
TYPE(u128);
TYPE(s128);

#undef TYPE
if (sup[extra].fmt_string == &fmt_class_string<u128>::format)
return -1;

return 0;
}
Expand Down
53 changes: 33 additions & 20 deletions Utilities/cfmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}

if (!ctx.type)
const usz src_type = src.type(ctx.args);

if (!ctx.type || src_type > 8)
{
ctx.type = static_cast<u8>(src.type(ctx.args));
ctx.type = static_cast<u8>(src_type);

if (!ctx.type)
{
Expand All @@ -379,7 +381,13 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)

// Sign-extended argument expected
const u64 val = src.template get<u64>(ctx.args);
const bool negative = ctx.type && static_cast<s64>(val) < 0;
bool negative = ctx.type && ctx.type <= 8 && static_cast<s64>(val) < 0;

if (ctx.type == 16)
{
u128 val2 = *reinterpret_cast<const u128*>(val);
negative = !!(val2 & (u128{1} << 127));
}

const usz start = out.size();

Expand All @@ -398,15 +406,14 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
out.push_back(' ');
}

if (ctx.type == 16)
if (ctx.type >= 16)
{
// TODO: support negative values (s128)
u128 val2 = *reinterpret_cast<u128*>(val);
write_decimal(val2, ctx.prec);
u128 val2 = *reinterpret_cast<const u128*>(val);
write_decimal(negative ? u128{} - val2 : val2, ctx.prec);
}
else
{
write_decimal(negative ? 0 - val : val, ctx.prec);
write_decimal(negative ? u64{} - val : val, ctx.prec);
}
}

Expand Down Expand Up @@ -438,9 +445,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}

if (!ctx.type)
const usz src_type = src.type(ctx.args);

if (!ctx.type || src_type > 8)
{
ctx.type = static_cast<u8>(src.type(ctx.args));
ctx.type = static_cast<u8>(src_type);

if (!ctx.type)
{
Expand Down Expand Up @@ -471,9 +480,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)

if ((ctx.alter && val) || !ctx.dot || ctx.prec)
{
if (ctx.type == 16)
if (ctx.type >= 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
u128 val2 = *reinterpret_cast<const u128*>(val);
write_octal(val2, ctx.prec);
}
else
Expand Down Expand Up @@ -504,9 +513,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}

if (!ctx.type)
const usz src_type = src.type(ctx.args);

if (!ctx.type || src_type > 8)
{
ctx.type = static_cast<u8>(src.type(ctx.args));
ctx.type = static_cast<u8>(src_type);

if (!ctx.type)
{
Expand Down Expand Up @@ -537,9 +548,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)

if ((ctx.alter && val) || !ctx.dot || ctx.prec)
{
if (ctx.type == 16)
if (ctx.type >= 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
u128 val2 = *reinterpret_cast<const u128*>(val);
write_hex(val2, ch == 'X', ctx.prec);
}
else
Expand Down Expand Up @@ -576,9 +587,11 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
break;
}

if (!ctx.type)
const usz src_type = src.type(ctx.args);

if (!ctx.type || src_type > 8)
{
ctx.type = static_cast<u8>(src.type(ctx.args));
ctx.type = static_cast<u8>(src_type);

if (!ctx.type)
{
Expand All @@ -599,9 +612,9 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)

if (!ctx.dot || ctx.prec)
{
if (ctx.type == 16)
if (ctx.type >= 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
u128 val2 = *reinterpret_cast<const u128*>(val);
write_decimal(val2, ctx.prec);
}
else
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/Modules/cellGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/Modules/cellGifDec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Cell/Modules/cellJpgDec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
10 changes: 5 additions & 5 deletions rpcs3/Emu/Io/Skylander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
100 changes: 90 additions & 10 deletions rpcs3/Emu/Memory/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,15 +495,24 @@ namespace vm
{
to_clear = for_all_range_locks(to_clear, [&](u64 addr2, u32 size2)
{
// TODO (currently not possible): handle 2 64K pages (inverse range), or more pages
if (u64 is_shared = g_shmem[addr2 >> 16]) [[unlikely]]
// Split and check every 64K page separately
for (u64 hi = addr2 >> 16, max = (addr2 + size2 - 1) >> 16; hi <= max; hi++)
{
addr2 = static_cast<u16>(addr2) | is_shared;
}
u64 addr3 = addr2;
u32 size3 = std::min<u64>(addr2 + size2, utils::align(addr2, 0x10000)) - addr2;

if (point - (addr2 / 128) <= (addr2 + size2 - 1) / 128 - (addr2 / 128)) [[unlikely]]
{
return 1;
if (u64 is_shared = g_shmem[hi]) [[unlikely]]
{
addr3 = static_cast<u16>(addr2) | is_shared;
}

if (point - (addr3 / 128) <= (addr3 + size3 - 1) / 128 - (addr3 / 128)) [[unlikely]]
{
return 1;
}

addr2 += size3;
size2 -= size3;
}

return 0;
Expand Down Expand Up @@ -1919,10 +1928,8 @@ namespace vm
return _map(addr, area_size, flags);
}

bool try_access(u32 addr, void* ptr, u32 size, bool is_write)
static bool try_access_internal(u32 addr, void* ptr, u32 size, bool is_write)
{
vm::writer_lock lock;

if (vm::check_addr(addr, is_write ? page_writable : page_readable, size))
{
void* src = vm::g_sudo_addr + addr;
Expand Down Expand Up @@ -1955,6 +1962,79 @@ namespace vm
return false;
}

bool try_access(u32 begin, void* ptr, u32 size, bool is_write)
{
auto* range_lock = alloc_range_lock(); // Released at the end of function

range_lock->store(begin | (u64{size} << 32));

for (u64 i = 0;; i++)
{
const u64 lock_val = g_range_lock.load();
const u64 is_share = g_shmem[begin >> 16].load();

u64 lock_addr = static_cast<u32>(lock_val); // -> u64
u32 lock_size = static_cast<u32>(lock_val << range_bits >> (range_bits + 32));

u64 addr = begin;

if ((lock_val & range_full_mask) == range_locked) [[likely]]
{
lock_size = 128;

if (is_share)
{
addr = static_cast<u16>(addr) | is_share;
lock_addr = lock_val;
}
}

if (addr + size <= lock_addr || addr >= lock_addr + lock_size) [[likely]]
{
if (vm::check_addr(begin, is_write ? page_writable : page_readable, size)) [[likely]]
{
const u64 new_lock_val = g_range_lock.load();

if (!new_lock_val || new_lock_val == lock_val) [[likely]]
{
break;
}
}
else
{
free_range_lock(range_lock);
return false;
}
}
else if (lock_val & range_readable && lock_val & range_writable)
{
// Probably a safe case of page protection change
break;
}
else if (!is_write && lock_val & range_readable)
{
// Same but for read-only access
break;
}
else if ((lock_val & range_full_mask) != range_locked)
{
free_range_lock(range_lock);
return false;
}

// Wait a bit before accessing global lock
range_lock->release(0);

busy_wait(200);

range_lock->store(begin | (u64{size} << 32));
}

const bool result = try_access_internal(begin, ptr, size, is_write);
free_range_lock(range_lock);
return result;
}

inline namespace ps3_
{
static utils::shm s_hook{0x800000000, ""};
Expand Down
16 changes: 8 additions & 8 deletions rpcs3/Emu/NP/np_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -219,15 +219,15 @@ 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:
if (tdata.len != 8 || !check_size(8))
{
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:
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions rpcs3/Emu/NP/np_notifications.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Loading