Files
wiicompiled/runtime/src/hle/gx/gx_utils.cpp
T
Michael G 5c76e2b0df feature: add apple silicon native macOS support (#81)
* feature: add apple silicon native macOS support - #81

* (macos): Fix crash

This fixes a crash when viewing the rear camera

* fix(macos): keep interpolated presentation on main thread

* fix(macos): supply Retro-WFC payload during setup

* perf(windows): compile out flat-memory fallback check

* remove duplicate smoke test

* test(macos): name and focus host platform tests

* fix(macos): validate Retro-WFC payload cache

* fix(payload): preserve staged file access failures

* Limit flat-page checks to variable-page hosts

---------

Co-authored-by: patchzyy <64382339+patchzyy@users.noreply.github.com>
2026-09-01 18:57:15 +02:00

77 lines
3.7 KiB
C++

#include "gx_internal.h"
#include "runtime_log.h"
extern "C" {
int g_gxFrameCount = 0;
int32_t g_scissorLeft = 0;
int32_t g_scissorTop = 0;
int32_t g_scissorWidth = 0;
int32_t g_scissorHeight = 0;
float g_viewportState[6] = {0.f, 0.f, 1.f, 1.f, 0.f, 1.f};
float g_projectionVector[7] = {1.f, 1.f, 0.f, 1.f, 0.f, -1.f, 0.f};
}
bool g_alphaCompareValid = false;
TexCopyState g_texCopyState;
GXColor DecodeGxColor(uint32_t colorWord) {
GXColor color{};
color.r = static_cast<uint8_t>((colorWord >> 24) & 0xFF);
color.g = static_cast<uint8_t>((colorWord >> 16) & 0xFF);
color.b = static_cast<uint8_t>((colorWord >> 8) & 0xFF);
color.a = static_cast<uint8_t>(colorWord & 0xFF);
return color;
}
void WriteGuestFloat(uint32_t addr, float value, const char* label) {
if (addr == 0) return;
try { Memory::WriteFloat32(addr, value); } catch (const Memory::AccessViolation& e) { LogMemoryError(RT_TAG_GX, label ? label : "GX write", e); }
}
void* GuestToHostPtr(uint32_t addr, size_t len) {
if (addr == 0) return nullptr;
#if defined(__APPLE__)
// The macOS flat guest map exposes separate host aliases for cached,
// uncached, and physical MEM1/MEM2 addresses. GX resources are identified
// by their host pointer, so all aliases of one guest allocation must use
// the same physical mapping before they reach Aurora. Kept macOS-only:
// changing which alias the other hosts hand out would re-key their existing
// GX resource identity.
addr = CanonicalizeGxMainRamAddress(addr);
#endif
try { return Memory::GetPointer(addr, len); } catch (const Memory::AccessViolation& e) { LogMemoryError(RT_TAG_GX, "GX guest pointer", e); return nullptr; }
}
void WriteGuest32(uint32_t addr, uint32_t value, const char* label) {
if (addr == 0) return;
try { Memory::Write32(addr, value); } catch (const Memory::AccessViolation& e) { LogMemoryError(RT_TAG_GX, label ? label : "GX write32", e); }
}
bool IsKnownTexFormat(uint32_t fmt) {
switch (fmt) {
case GX_TF_I4: case GX_TF_I8: case GX_TF_IA4: case GX_TF_IA8: case GX_TF_RGB565: case GX_TF_RGB5A3: case GX_TF_RGBA8: case GX_TF_CMPR: case GX_TF_C4: case GX_TF_C8: case GX_TF_C14X2: case GX_TF_Z8: case GX_TF_Z16: case GX_TF_Z24X8: case GX_CTF_R4: case GX_CTF_RA4: case GX_CTF_RA8: case GX_CTF_YUVA8: case GX_CTF_A8: case GX_CTF_R8: case GX_CTF_G8: case GX_CTF_B8: case GX_CTF_RG8: case GX_CTF_GB8: case GX_CTF_Z4: case GX_CTF_Z8M: case GX_CTF_Z8L: case GX_CTF_Z16L: return true;
default: return false;
}
}
bool IsPaletteTexFormat(uint32_t fmt) { return fmt == GX_TF_C4 || fmt == GX_TF_C8 || fmt == GX_TF_C14X2; }
bool IsKnownTlutFormat(uint32_t fmt) { switch (fmt) { case GX_TL_IA8: case GX_TL_RGB565: case GX_TL_RGB5A3: return true; default: return false; } }
// Returns false when the guest's TLUT descriptor is unusable. Callers must not
// hand the descriptor to aurora in that case: aurora reads entries*2 bytes from
// the pointer at load time, so a bad address or entry count is an out-of-range
// native read. This used to only log and let the call through, which is why the
// return value now exists.
bool ValidateTlutData(uint32_t objAddr, const TlutObjMeta& meta) {
if (meta.dataAddr == 0 || meta.entries == 0) { RT_LOGF(RT_TAG_GX, "invalid TLUT data (oa=0x%08X)\n", objAddr); return false; }
if (!IsKnownTlutFormat(meta.format)) { RT_LOGF(RT_TAG_GX, "invalid TLUT format 0x%X (oa=0x%08X)\n", meta.format, objAddr); return false; }
if (!Memory::Contains(meta.dataAddr, static_cast<uint32_t>(meta.entries) * 2u)) {
RT_LOGF(RT_TAG_GX, "invalid TLUT range (oa=0x%08X data=0x%08X entries=%u)\n", objAddr, meta.dataAddr, meta.entries);
return false;
}
return true;
}