mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 08:00:25 +02:00
Merge pull request #10 from mitch030504/claude/project-thread-4jegmq
Port three small fixes from the DarthMDev and KartPad forks
This commit is contained in:
5 files changed
+167
-30
No files matched your search
@@ -221,9 +221,13 @@ void render(const wgpu::RenderPassEncoder& pass) noexcept {
|
||||
ImGui_ImplSDLRenderer3_RenderDrawData(data, renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
} else {
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PushDebugGroup("Aurora: Dear Imgui");
|
||||
#endif
|
||||
ImGui_ImplWGPU_RenderDrawData(data, pass.Get());
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PopDebugGroup();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,9 +291,13 @@ void render(const wgpu::RenderPassEncoder& pass, const ImDrawData* data) noexcep
|
||||
if (g_useSdlRenderer || data == nullptr) {
|
||||
return;
|
||||
}
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PushDebugGroup("Aurora: Dear Imgui");
|
||||
#endif
|
||||
ImGui_ImplWGPU_RenderDrawData(const_cast<ImDrawData*>(data), pass.Get());
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PopDebugGroup();
|
||||
#endif
|
||||
}
|
||||
|
||||
StereoOverlay latch_stereo_overlay() noexcept {
|
||||
@@ -303,9 +311,13 @@ bool render_draw_data(const wgpu::RenderPassEncoder& pass, ImDrawData* data) noe
|
||||
if (g_useSdlRenderer || data == nullptr || ImGui::GetCurrentContext() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PushDebugGroup("Aurora: Dear Imgui headset panel");
|
||||
#endif
|
||||
ImGui_ImplWGPU_RenderDrawData(data, pass.Get());
|
||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||
pass.PopDebugGroup();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -294,14 +295,57 @@ inline bool ReadExact(const std::filesystem::path& hostPath,
|
||||
HostReadFailure& failure) {
|
||||
failure = HostReadFailure::None;
|
||||
|
||||
std::ifstream file(hostPath, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
failure = HostReadFailure::MissingFile;
|
||||
return false;
|
||||
// DVD callbacks run on the guest thread, often reading the same stream
|
||||
// file many times per second. Reuse a bounded set of handles without
|
||||
// sharing seek positions with another host thread.
|
||||
struct OpenFile {
|
||||
std::filesystem::path path;
|
||||
std::ifstream stream;
|
||||
std::streamoff size = 0;
|
||||
std::filesystem::file_time_type modified{};
|
||||
uint64_t lastUse = 0;
|
||||
};
|
||||
static thread_local std::vector<OpenFile> openFiles;
|
||||
static thread_local uint64_t useCount = 0;
|
||||
constexpr size_t kMaxOpenFiles = 8;
|
||||
|
||||
auto found = std::find_if(openFiles.begin(), openFiles.end(),
|
||||
[&](const OpenFile& entry) { return entry.path == hostPath; });
|
||||
if (found != openFiles.end()) {
|
||||
std::error_code ec;
|
||||
const auto modified = std::filesystem::last_write_time(hostPath, ec);
|
||||
if (ec || modified != found->modified) {
|
||||
openFiles.erase(found);
|
||||
found = openFiles.end();
|
||||
}
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
const std::streamoff fileSize = file.tellg();
|
||||
if (found == openFiles.end()) {
|
||||
std::ifstream file(hostPath, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
failure = HostReadFailure::MissingFile;
|
||||
return false;
|
||||
}
|
||||
file.seekg(0, std::ios::end);
|
||||
const std::streamoff size = file.tellg();
|
||||
if (size < 0) {
|
||||
failure = HostReadFailure::BadOffset;
|
||||
return false;
|
||||
}
|
||||
std::error_code ec;
|
||||
const auto modified = std::filesystem::last_write_time(hostPath, ec);
|
||||
if (openFiles.size() == kMaxOpenFiles) {
|
||||
const auto oldest = std::min_element(openFiles.begin(), openFiles.end(),
|
||||
[](const OpenFile& a, const OpenFile& b) { return a.lastUse < b.lastUse; });
|
||||
openFiles.erase(oldest);
|
||||
}
|
||||
openFiles.push_back({hostPath, std::move(file), size,
|
||||
ec ? std::filesystem::file_time_type{} : modified, 0});
|
||||
found = std::prev(openFiles.end());
|
||||
}
|
||||
found->lastUse = ++useCount;
|
||||
|
||||
const std::streamoff fileSize = found->size;
|
||||
if (fileSize < 0 ||
|
||||
offset > static_cast<uint64_t>(std::numeric_limits<std::streamoff>::max()) ||
|
||||
offset >= static_cast<uint64_t>(fileSize)) {
|
||||
@@ -316,17 +360,20 @@ inline bool ReadExact(const std::filesystem::path& hostPath,
|
||||
}
|
||||
|
||||
std::vector<uint8_t> staged(length);
|
||||
file.seekg(static_cast<std::streamoff>(offset), std::ios::beg);
|
||||
if (!file) {
|
||||
found->stream.clear();
|
||||
found->stream.seekg(static_cast<std::streamoff>(offset), std::ios::beg);
|
||||
if (!found->stream) {
|
||||
failure = HostReadFailure::BadOffset;
|
||||
openFiles.erase(found);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length != 0) {
|
||||
file.read(reinterpret_cast<char*>(staged.data()),
|
||||
static_cast<std::streamsize>(length));
|
||||
if (file.gcount() != static_cast<std::streamsize>(length)) {
|
||||
found->stream.read(reinterpret_cast<char*>(staged.data()),
|
||||
static_cast<std::streamsize>(length));
|
||||
if (found->stream.gcount() != static_cast<std::streamsize>(length)) {
|
||||
failure = HostReadFailure::ShortRead;
|
||||
openFiles.erase(found);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
#include "hle_stubs.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include "memory.h"
|
||||
#include "recomp_mod_loader.h"
|
||||
#include "runtime_log.h"
|
||||
|
||||
extern "C" void GxNotifyGuestRamDmaWrite(uint32_t addr, uint32_t size);
|
||||
|
||||
// Native because a crafted Yaz0 run writes past the caller's buffer
|
||||
// (github.com/vabold/szsHaxx)
|
||||
// https://github.com/vabold/Kinoko/blob/main/source/egg/core/Decomp.cc
|
||||
|
||||
extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
{
|
||||
const uint32_t expandSize = (static_cast<uint32_t>(MemoryInline::FlatRead8(src + 4)) << 24) |
|
||||
(static_cast<uint32_t>(MemoryInline::FlatRead8(src + 5)) << 16) |
|
||||
(static_cast<uint32_t>(MemoryInline::FlatRead8(src + 6)) << 8) |
|
||||
static_cast<uint32_t>(MemoryInline::FlatRead8(src + 7));
|
||||
|
||||
template <typename Access>
|
||||
static uint32_t DecodeSZS(uint32_t src, uint32_t expandSize, Access& access) {
|
||||
uint32_t srcIdx = 16;
|
||||
uint32_t dstIdx = 0;
|
||||
uint32_t mask = 0;
|
||||
@@ -22,15 +21,15 @@ extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
|
||||
while (static_cast<int32_t>(dstIdx) < static_cast<int32_t>(expandSize)) {
|
||||
if (mask == 0) {
|
||||
flags = MemoryInline::FlatRead8(src + srcIdx++);
|
||||
flags = access.ReadSource(srcIdx++);
|
||||
mask = 0x80;
|
||||
}
|
||||
|
||||
if ((flags & mask) != 0) {
|
||||
MemoryInline::FlatWrite8(dst + dstIdx++, MemoryInline::FlatRead8(src + srcIdx++));
|
||||
access.WriteOutput(dstIdx++, access.ReadSource(srcIdx++));
|
||||
} else {
|
||||
const uint32_t high = MemoryInline::FlatRead8(src + srcIdx);
|
||||
const uint32_t low = MemoryInline::FlatRead8(src + srcIdx + 1);
|
||||
const uint32_t high = access.ReadSource(srcIdx);
|
||||
const uint32_t low = access.ReadSource(srcIdx + 1);
|
||||
srcIdx += 2;
|
||||
|
||||
const uint32_t rep = (high << 8) | low;
|
||||
@@ -48,7 +47,7 @@ extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
uint32_t count = rep >> 12;
|
||||
count = count != 0
|
||||
? count + 2
|
||||
: static_cast<uint32_t>(MemoryInline::FlatRead8(src + srcIdx++)) + 18;
|
||||
: static_cast<uint32_t>(access.ReadSource(srcIdx++)) + 18;
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
if (dstIdx >= expandSize) {
|
||||
@@ -59,7 +58,7 @@ extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
"The game stopped decoding a malformed Yaz0 file.");
|
||||
std::abort();
|
||||
}
|
||||
MemoryInline::FlatWrite8(dst + dstIdx++, MemoryInline::FlatRead8(dst + copyIdx++));
|
||||
access.WriteOutput(dstIdx++, access.ReadOutput(copyIdx++));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,5 +68,61 @@ extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
return expandSize;
|
||||
}
|
||||
|
||||
struct GuestSZSAccess {
|
||||
uint32_t src;
|
||||
uint32_t dst;
|
||||
|
||||
uint8_t ReadSource(uint32_t offset) const { return MemoryInline::FlatRead8(src + offset); }
|
||||
uint8_t ReadOutput(uint32_t offset) const { return MemoryInline::FlatRead8(dst + offset); }
|
||||
void WriteOutput(uint32_t offset, uint8_t value) const {
|
||||
MemoryInline::FlatWrite8(dst + offset, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct HostSZSAccess {
|
||||
const uint8_t* src;
|
||||
uint8_t* dst;
|
||||
|
||||
uint8_t ReadSource(uint32_t offset) const { return src[offset]; }
|
||||
uint8_t ReadOutput(uint32_t offset) const { return dst[offset]; }
|
||||
void WriteOutput(uint32_t offset, uint8_t value) const { dst[offset] = value; }
|
||||
};
|
||||
|
||||
static bool HasDeferredReadPages(uint32_t address, size_t length) {
|
||||
const uint32_t first = address >> MemoryInline::kPageShift;
|
||||
const uint32_t last = static_cast<uint32_t>(
|
||||
(static_cast<uint64_t>(address) + length - 1) >> MemoryInline::kPageShift);
|
||||
for (uint32_t page = first; page <= last; ++page) {
|
||||
if (MemoryInline::g_deferredReadCoveredPages[page] != 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" uint32_t EGG_Decomp_decodeSZS_80218c2c(uint32_t src, uint32_t dst)
|
||||
{
|
||||
const uint32_t expandSize = (static_cast<uint32_t>(MemoryInline::FlatRead8(src + 4)) << 24) |
|
||||
(static_cast<uint32_t>(MemoryInline::FlatRead8(src + 5)) << 16) |
|
||||
(static_cast<uint32_t>(MemoryInline::FlatRead8(src + 6)) << 8) |
|
||||
static_cast<uint32_t>(MemoryInline::FlatRead8(src + 7));
|
||||
|
||||
// A token produces at least one byte; all-literal data is the largest
|
||||
// valid input (one flag per eight output bytes). Three extra bytes cover
|
||||
// the final malformed run before its output-overrun check aborts.
|
||||
const size_t maxSourceBytes = 16ull + expandSize + (static_cast<uint64_t>(expandSize) + 7) / 8 + 3;
|
||||
if (expandSize != 0 && expandSize <= static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) &&
|
||||
!GuestFlat::RequiresCheckedAccess() &&
|
||||
Memory::Contains(src, maxSourceBytes) && Memory::Contains(dst, expandSize) &&
|
||||
!HasDeferredReadPages(src, maxSourceBytes) && !HasDeferredReadPages(dst, expandSize) &&
|
||||
!RecompMod::ExecutableWriteGuardMayHit(dst, expandSize)) {
|
||||
HostSZSAccess access{Memory::GetPointer(src, maxSourceBytes), Memory::GetPointer(dst, expandSize)};
|
||||
const uint32_t decoded = DecodeSZS(src, expandSize, access);
|
||||
GxNotifyGuestRamDmaWrite(dst, decoded);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
GuestSZSAccess access{src, dst};
|
||||
return DecodeSZS(src, expandSize, access);
|
||||
}
|
||||
|
||||
PPC_NATIVE_OVERRIDE(80218C2C, EGG_Decomp_decodeSZS_80218c2c, uint32_t,
|
||||
(uint32_t src, uint32_t dst), (src, dst));
|
||||
@@ -54,6 +54,9 @@ constexpr int kMaxSslSessions = 4;
|
||||
struct SslSession {
|
||||
bool active = false;
|
||||
bool handshaked = false;
|
||||
// A failed POSIX TLS write cannot be resumed with a new guest buffer.
|
||||
// Keep the slot and socket ownership intact until explicit teardown.
|
||||
bool failed = false;
|
||||
bool plaintextWfc = false;
|
||||
uint32_t socketFd = UINT32_MAX;
|
||||
NativeSocket native = kInvalidSocket;
|
||||
@@ -761,6 +764,14 @@ static int32_t SslHandshakeImpl(SslSession& ssl) {
|
||||
return SSL_OK;
|
||||
}
|
||||
|
||||
static int32_t FailSslWrite(SslSession& ssl) {
|
||||
ssl.failed = true;
|
||||
// Stop transport I/O without deleting the guest descriptor or freeing a
|
||||
// session still referenced by the IOCTLV_NET_SSL_WRITE caller.
|
||||
::shutdown(ssl.native, SHUT_RDWR);
|
||||
return SSL_ERR_FAILED;
|
||||
}
|
||||
|
||||
static int32_t SslWrite(SslSession& ssl, const uint8_t* data, uint32_t size) {
|
||||
if (!data || size == 0) {
|
||||
return SSL_ERR_ZERO;
|
||||
@@ -795,12 +806,11 @@ static int32_t SslWrite(SslSession& ssl, const uint8_t* data, uint32_t size) {
|
||||
}
|
||||
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
if (std::chrono::steady_clock::now() >= writeDeadline) {
|
||||
DeleteWiiSocket(ssl.socketFd);
|
||||
return SSL_ERR_FAILED;
|
||||
return FailSslWrite(ssl);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return SSL_ERR_FAILED;
|
||||
return FailSslWrite(ssl);
|
||||
}
|
||||
return static_cast<int32_t>(totalWritten);
|
||||
}
|
||||
@@ -842,6 +852,9 @@ static int32_t SslRead(SslSession& ssl, uint8_t* out, uint32_t size) {
|
||||
// The handshake runs on every SSL read/write, so a failure repeats for as long
|
||||
// as the session lives; report only the first one.
|
||||
static int32_t SslHandshake(SslSession& ssl) {
|
||||
if (ssl.failed) {
|
||||
return SSL_ERR_FAILED;
|
||||
}
|
||||
const int32_t result = SslHandshakeImpl(ssl);
|
||||
if (result != SSL_OK && !ssl.loggedHandshakeFail) {
|
||||
ssl.loggedHandshakeFail = true;
|
||||
@@ -947,6 +960,11 @@ int32_t HandleSslIoctlv(uint32_t cmd, const std::vector<IoVector>& in, const std
|
||||
WriteSslReturn(in, SSL_ERR_ID);
|
||||
return 0;
|
||||
}
|
||||
// Reject before NAS buffering can acknowledge data on a failed session.
|
||||
if (g_sslSessions[sslId].failed) {
|
||||
WriteSslReturn(in, SSL_ERR_FAILED);
|
||||
return 0;
|
||||
}
|
||||
if (out.size() < 2 || !out[1].address) {
|
||||
WriteSslReturn(in, SSL_ERR_FAILED);
|
||||
return 0;
|
||||
|
||||
@@ -104,10 +104,15 @@ extern "C" void DVDInit_8015EA1C();
|
||||
extern "C" uint32_t g_dvdFstReservedBase;
|
||||
extern "C" uint32_t g_dvdFstReservedSize;
|
||||
|
||||
// Byte-wise copy into guest RAM plus the DMA notification the GX caches need.
|
||||
// DVD DMA normally targets ordinary RAM. Keep scalar writes for executable
|
||||
// ranges so the translated-code write guard still sees every modified byte.
|
||||
static void CopyToGuestAsDma(uint32_t dest, const uint8_t* data, size_t size) {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
Memory::Write8(dest + static_cast<uint32_t>(i), data[i]);
|
||||
if (size != 0 && !RecompMod::ExecutableWriteGuardMayHit(dest, size)) {
|
||||
std::memcpy(Memory::GetPointer(dest, size), data, size);
|
||||
} else {
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
Memory::Write8(dest + static_cast<uint32_t>(i), data[i]);
|
||||
}
|
||||
}
|
||||
GxNotifyGuestRamDmaWrite(dest, static_cast<uint32_t>(size));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user