mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-10-09 02:18:27 -04:00
6f14bde26a
* Preserve interrupted registers and unwind alarm guards before rescheduling Adapt the RFL interrupt-context and alarm reschedule fixes from KartPad ed8e4ca and 0c9bff0. Keep caller registers private and release the recursion guard before a woken fiber can pump callbacks. * Keep local Wii identity services available when networking is disabled Adapt KartPad a0f3fb5. Only IP and SSL devices require network access; KD request/time and NCD management remain available for offline save and license initialization. * Share repeated LR continuation dispatch in translated functions Adapt KartPad be91d8f/a3f90eb without its floating-point ABI changes. Preserve upstream continuation discovery and all resume labels. Validation: 640 translator tests passed. * Reject inconsistent GPU cache sizes before allocation or copying Adapt KartPad runtime 70951022. Validate raw lengths, compression tags and Zstd frame lengths on the size probe as well as the fetch. Tested against malformed SQLite rows and valid raw/compressed round trips. * Wake compiler workers when pipeline work becomes runnable Adapt KartPad runtime 956d811e. Wake all consumers of the shared condition variable after queue insertion or promotion; retain upstream desktop prewarm policy. A blocked-compiler probe verified progress by an idle worker. * Reuse and release one Metal view per SDL window Adapt KartPad 3606741. Surface recreation reuses the existing view and window property cleanup owns its lifetime. Reviewed against SDL3 cleanup semantics; Apple hardware validation remains outstanding. * Avoid overreading packed three-byte vertex attributes Adapt KartPad 0f6b274. Do not read a second storage word when all three requested bytes fit in the first. Preserve upstream depth and fog corrections. * Keep interpolation history within each split-screen viewport Adapt KartPad d6299b5. Scope exact, material and sibling-palette matching to the logical viewport so identical meshes from different cameras cannot share transforms. * Report graphics startup failures and safely clean up partial ImGui initialization Adapt KartPad runtime 70dc9380 and c4566e50 using the existing WiiCompiled exception/reporting path. A dummy-video-driver probe verified error return and repeated partial shutdown without aborting. * Preserve GX draw boundaries and GPU staging and readback state Adapt the validated renderer fixes from KartPad runtime 31add0c3, 7393dafe, b7f515de, cf46a9c7, fad42a7b, 7cd09b69, 9feea6b2 and Android 2505ae22 to current upstream. Preserve complete primitives and fresh vertex layouts, split staging batches before overflow, retain offscreen state, scope asynchronous callbacks and frame state, and complete texture-copy sources. Add unit regressions and an optional ROM-free GPU pixel test. Validation: 250 GX tests and actual D3D12 pixel/readback, capacity, interpolation and frame-worker checks passed with Dawn validation enabled.
112 lines
3.8 KiB
C++
112 lines
3.8 KiB
C++
#include <dolphin/vi.h>
|
|
|
|
#include "../../window.hpp"
|
|
#include "aurora/math.hpp"
|
|
#include "vi_internal.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <optional>
|
|
#include <mutex>
|
|
|
|
namespace aurora::vi {
|
|
std::optional<GXRenderModeObj> g_renderMode;
|
|
namespace {
|
|
std::atomic<float> g_presentAspectCorrection{1.f};
|
|
std::mutex g_renderModeMutex;
|
|
|
|
float calculate_present_aspect_correction(const GXRenderModeObj& rm) noexcept {
|
|
if (rm.viWidth == 0 || rm.viHeight == 0) {
|
|
return 1.f;
|
|
}
|
|
|
|
// Dolphin derives the displayed aspect from the VI active region instead of assuming an exact
|
|
// 4:3 or 16:9 signal. These are its BT.601 active sample and line counts.
|
|
const auto format = (static_cast<uint32_t>(rm.viTVmode) >> 2) & 0x7u;
|
|
const bool pal = format == VI_PAL || format == VI_DEBUG_PAL;
|
|
const float nominalActiveWidth =
|
|
pal ? 864.f * (52.f / 64.f) : 858.f * (52.655555f / 63.555555f);
|
|
const float nominalActiveHeight = pal ? 576.f : 486.f;
|
|
const float horizontalFill = static_cast<float>(rm.viWidth) / nominalActiveWidth;
|
|
const float verticalFill = static_cast<float>(rm.viHeight) / nominalActiveHeight;
|
|
return horizontalFill / verticalFill;
|
|
}
|
|
|
|
Vec2<uint32_t> render_mode_size_locked() noexcept {
|
|
if (!g_renderMode) {
|
|
return {640, 528};
|
|
}
|
|
// GX has a fixed 640x528 EFB workspace. Games can configure a narrower visible framebuffer, but
|
|
// effects such as MKW's DOF use the remaining EFB area as scratch.
|
|
return {std::max<uint32_t>(g_renderMode->fbWidth, 640), std::max<uint32_t>(g_renderMode->efbHeight, 528)};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Vec2<uint32_t> render_mode_size() noexcept {
|
|
std::lock_guard lock(g_renderModeMutex);
|
|
return render_mode_size_locked();
|
|
}
|
|
|
|
void configure(const GXRenderModeObj* rm) noexcept {
|
|
bool sizeChanged = false;
|
|
{
|
|
std::lock_guard lock(g_renderModeMutex);
|
|
const auto oldSize = render_mode_size_locked();
|
|
if (rm == nullptr) {
|
|
g_renderMode.reset();
|
|
} else {
|
|
g_renderMode = *rm;
|
|
g_presentAspectCorrection.store(calculate_present_aspect_correction(*rm), std::memory_order_release);
|
|
}
|
|
if (rm == nullptr) {
|
|
g_presentAspectCorrection.store(1.f, std::memory_order_release);
|
|
}
|
|
sizeChanged = render_mode_size_locked() != oldSize;
|
|
}
|
|
// Never hold the mode lock across a resize request or a renderer callback.
|
|
if (sizeChanged) {
|
|
window::request_frame_buffer_resize();
|
|
}
|
|
}
|
|
|
|
Vec2<uint32_t> configured_fb_size() noexcept {
|
|
return render_mode_size();
|
|
}
|
|
|
|
Vec2<uint32_t> visible_fb_size() noexcept {
|
|
std::lock_guard lock(g_renderModeMutex);
|
|
if (!g_renderMode) {
|
|
return {640, 528};
|
|
}
|
|
return {g_renderMode->fbWidth, g_renderMode->efbHeight};
|
|
}
|
|
|
|
float present_aspect_correction() noexcept {
|
|
return g_presentAspectCorrection.load(std::memory_order_acquire);
|
|
}
|
|
} // namespace aurora::vi
|
|
|
|
extern "C" {
|
|
void VIInit() {}
|
|
void VIConfigure(const GXRenderModeObj* rm) { aurora::vi::configure(rm); }
|
|
void VIConfigurePan(u16 xOrg, u16 yOrg, u16 width, u16 height) {
|
|
(void)xOrg;
|
|
(void)yOrg;
|
|
(void)width;
|
|
(void)height;
|
|
}
|
|
u32 VIGetTvFormat() { return 0; }
|
|
void VIFlush() {}
|
|
|
|
void VISetWindowTitle(const char* title) { aurora::window::set_title(title); }
|
|
void VISetWindowFullscreen(bool fullscreen) { aurora::window::set_fullscreen(fullscreen); }
|
|
bool VIGetWindowFullscreen() { return aurora::window::get_fullscreen(); }
|
|
void VISetWindowSize(uint32_t width, uint32_t height) { aurora::window::set_window_size(width, height); }
|
|
void VISetWindowPosition(uint32_t x, uint32_t y) { aurora::window::set_window_position(x, y); }
|
|
void VICenterWindow() { aurora::window::center_window(); }
|
|
void VISetFrameBufferScale(float scale) { aurora::window::set_frame_buffer_scale(scale); }
|
|
void VILockAspectRatio(int width, int height) { aurora::window::lock_present_aspect_ratio(width, height); }
|
|
void VIUnlockAspectRatio() { aurora::window::unlock_present_aspect_ratio(); }
|
|
}
|