|
|
|
|
@@ -1,8 +1,12 @@
|
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
|
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
|
|
#include <boost/range/algorithm_ext/erase.hpp>
|
|
|
|
|
@@ -187,7 +191,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
|
|
|
|
|
buffer_w_descriptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size;
|
|
|
|
|
buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size;
|
|
|
|
|
|
|
|
|
|
if (!command_header->IsTipc()) {
|
|
|
|
|
// Padding to align to 16 bytes
|
|
|
|
|
@@ -294,7 +298,15 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write the domain objects to the command buffer, these go after the raw untranslated data.
|
|
|
|
|
// TODO(Subv): This completely ignores C buffers.
|
|
|
|
|
|
|
|
|
|
if (buffer_c_offset != 0 && !buffer_c_descriptors.empty()) {
|
|
|
|
|
constexpr u32 WORDS_PER_DESCRIPTOR = sizeof(IPC::BufferDescriptorC) / sizeof(u32);
|
|
|
|
|
u32 descriptor_offset = buffer_c_offset;
|
|
|
|
|
for (const auto& descriptor : buffer_c_descriptors) {
|
|
|
|
|
std::memcpy(&cmd_buf[descriptor_offset], &descriptor, sizeof(descriptor));
|
|
|
|
|
descriptor_offset += WORDS_PER_DESCRIPTOR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GetManager()->IsDomain()) {
|
|
|
|
|
current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size());
|
|
|
|
|
@@ -393,10 +405,14 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
|
|
|
|
|
const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
|
|
|
|
|
BufferDescriptorB()[buffer_index].Size()};
|
|
|
|
|
const std::size_t buffer_size{GetWriteBufferSize(buffer_index)};
|
|
|
|
|
if (buffer_size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "WriteBuffer target index {} has zero capacity", buffer_index);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (size > buffer_size) {
|
|
|
|
|
LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
|
|
|
|
|
buffer_size);
|
|
|
|
|
size = buffer_size; // TODO(bunnei): This needs to be HW tested
|
|
|
|
|
LOG_WARNING(Core, "size ({:016X}) is greater than buffer_size ({:016X}); clamping",
|
|
|
|
|
size, buffer_size);
|
|
|
|
|
size = buffer_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_buffer_b) {
|
|
|
|
|
@@ -418,15 +434,25 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
|
|
|
|
|
|
|
|
|
|
std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size,
|
|
|
|
|
std::size_t buffer_index) const {
|
|
|
|
|
if (buffer_index >= BufferDescriptorB().size() || size == 0) {
|
|
|
|
|
if (buffer_index >= BufferDescriptorB().size()) {
|
|
|
|
|
LOG_WARNING(Core, "WriteBufferB invalid buffer index {}", buffer_index);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "skip empty buffer write (B)");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto buffer_size{BufferDescriptorB()[buffer_index].Size()};
|
|
|
|
|
if (buffer_size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "WriteBufferB target index {} has zero capacity", buffer_index);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (size > buffer_size) {
|
|
|
|
|
LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
|
|
|
|
|
buffer_size);
|
|
|
|
|
size = buffer_size; // TODO(bunnei): This needs to be HW tested
|
|
|
|
|
LOG_WARNING(Core, "size ({:016X}) is greater than buffer_size ({:016X}); clamping",
|
|
|
|
|
size, buffer_size);
|
|
|
|
|
size = buffer_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
|
|
|
|
|
@@ -435,15 +461,25 @@ std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size
|
|
|
|
|
|
|
|
|
|
std::size_t HLERequestContext::WriteBufferC(const void* buffer, std::size_t size,
|
|
|
|
|
std::size_t buffer_index) const {
|
|
|
|
|
if (buffer_index >= BufferDescriptorC().size() || size == 0) {
|
|
|
|
|
if (buffer_index >= BufferDescriptorC().size()) {
|
|
|
|
|
LOG_WARNING(Core, "WriteBufferC invalid buffer index {}", buffer_index);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "skip empty buffer write (C)");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto buffer_size{BufferDescriptorC()[buffer_index].Size()};
|
|
|
|
|
if (buffer_size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "WriteBufferC target index {} has zero capacity", buffer_index);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (size > buffer_size) {
|
|
|
|
|
LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
|
|
|
|
|
buffer_size);
|
|
|
|
|
size = buffer_size; // TODO(bunnei): This needs to be HW tested
|
|
|
|
|
LOG_WARNING(Core, "size ({:016X}) is greater than buffer_size ({:016X}); clamping",
|
|
|
|
|
size, buffer_size);
|
|
|
|
|
size = buffer_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size);
|
|
|
|
|
@@ -473,12 +509,20 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons
|
|
|
|
|
ASSERT_OR_EXECUTE_MSG(
|
|
|
|
|
BufferDescriptorB().size() > buffer_index, { return 0; },
|
|
|
|
|
"BufferDescriptorB invalid buffer_index {}", buffer_index);
|
|
|
|
|
return BufferDescriptorB()[buffer_index].Size();
|
|
|
|
|
const auto size = BufferDescriptorB()[buffer_index].Size();
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "BufferDescriptorB index {} has zero size", buffer_index);
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
} else {
|
|
|
|
|
ASSERT_OR_EXECUTE_MSG(
|
|
|
|
|
BufferDescriptorC().size() > buffer_index, { return 0; },
|
|
|
|
|
"BufferDescriptorC invalid buffer_index {}", buffer_index);
|
|
|
|
|
return BufferDescriptorC()[buffer_index].Size();
|
|
|
|
|
const auto size = BufferDescriptorC()[buffer_index].Size();
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
LOG_WARNING(Core, "BufferDescriptorC index {} has zero size", buffer_index);
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|