Remove EEDiffVerify: a live toggle in front of a dead diagnostic

EEDiffVerify was a throwaway EE recompiler-vs-interpreter differential
verifier, written to pin the True Crime NYC (SLUS-21106) texture-decompressor
corruption. It worked by emitting snapshot/verify hooks around each
straight-line op and re-running that op on the interpreter with stores
captured rather than applied.

Those hooks lived in the pre-transplant arm64/mac EE recompiler and in
vtlb.cpp, and 2eb9ec659c ("refactor: move Android frontend to platforms/android
on single shared core") dropped both. What survived is the shell:
g_ee_diff_verify is read by nothing, and eeDiffSnapshotPre, eeDiffVerify and
eeDiffCaptureStore are called by nothing.

The Android toggle in front of it stayed fully wired, so flipping it set a
flag no one reads and reset the EE recompiler - a visible hitch in exchange
for nothing at all.

pcsx2-eerunner covers this ground better anyway: two-pass offline JIT-vs-interp
localization over a full VM boot, so it is game-faithful by construction,
with --divtrace for first-divergent-op and --rec-fallback for group bisects.

Removes the module, its Android JNI pair, the NativeApp declarations, the
Recompiler-tab toggle and its now-empty Diagnostics header, the search-index
entry, and the three strings across all 19 translations.
This commit is contained in:
Brian Degenhardt
2026-07-26 19:34:05 -07:00
parent 7aadd3ae64
commit 15eb94fb74
27 changed files with 1 additions and 542 deletions
+1 -3
View File
@@ -1180,10 +1180,8 @@ if(ANDROID)
GS/Renderers/Common/GSGPUProfilePrivate.h)
list(APPEND pcsx2Sources
Android/AndroidStubs.cpp
Android/AndroidPcapStubs.cpp
EEDiffVerify.cpp)
Android/AndroidPcapStubs.cpp)
list(APPEND pcsx2Headers
EEDiffVerify.h
AndroidPerfBuckets.h
PS1DrvTrace.h)
# Oboe is the Android audio backend consumed by Host/OboeAudioStream.cpp.
-356
View File
@@ -1,356 +0,0 @@
// SPDX-License-Identifier: GPL-3.0+
//
// @@EEDIFF@@ THROWAWAY DIAGNOSTIC — EE recompiler-vs-interpreter differential verifier.
// See EEDiffVerify.h for the design overview. This file is the core: snapshot, the
// interpreter re-run with store-capture, and the compare/report.
#include "EEDiffVerify.h"
#include "R5900.h"
#include "R5900OpcodeTables.h"
#include "Memory.h"
#include "common/Console.h"
#include <cstdio>
#include <cstring>
// --------------------------------------------------------------------------------------
// Global switches
// --------------------------------------------------------------------------------------
volatile bool g_ee_diff_verify = false;
bool g_ee_diff_capture_stores = false;
void eeDiffSetEnabled(bool enabled) { g_ee_diff_verify = enabled; }
bool eeDiffGetEnabled() { return g_ee_diff_verify; }
namespace
{
// Snapshot of the guest register state taken BEFORE the recompiled op runs (via
// eeDiffSnapshotPre). This is the interpreter's input for the re-run.
struct EeDiffRegs
{
GPR_reg gpr[32];
GPR_reg hi;
GPR_reg lo;
u32 sa;
u32 pc;
};
EeDiffRegs g_diff_pre; // regs at op entry (rec == interp input here)
EeDiffRegs g_diff_recpost; // regs after the recompiled op ran (rec ground-truth to match)
// Captured interpreter stores for the op currently being verified.
struct EeDiffStore
{
u32 addr;
u32 bits; // 8/16/32/64/128
u64 lo;
u64 hi; // only for 128-bit
};
constexpr u32 EEDIFF_MAX_STORES = 8; // a single EE op stores at most a 128-bit quad
EeDiffStore g_diff_stores[EEDIFF_MAX_STORES];
u32 g_diff_store_count = 0;
// Log a bounded number of divergences (enough to characterize a systematic decompressor
// miscompile across several ops) without flooding logcat. False positives are now filtered at
// the source (RAM-only), so this budget is spent on real divergences.
u32 g_diff_reported = 0;
constexpr u32 EEDIFF_MAX_REPORTS = 64;
void snapshotInto(EeDiffRegs& dst)
{
std::memcpy(dst.gpr, cpuRegs.GPR.r, sizeof(dst.gpr));
dst.hi = cpuRegs.HI;
dst.lo = cpuRegs.LO;
dst.sa = cpuRegs.sa;
dst.pc = cpuRegs.pc;
}
void restoreFrom(const EeDiffRegs& src)
{
std::memcpy(cpuRegs.GPR.r, src.gpr, sizeof(src.gpr));
cpuRegs.HI = src.hi;
cpuRegs.LO = src.lo;
cpuRegs.sa = src.sa;
cpuRegs.pc = src.pc;
}
// Read the real (rec-written) memory at a captured store's address so we can compare it
// against what the interpreter WOULD have written. Uses the same vtlb read path the
// interpreter loads use, so it sees exactly what the rec committed. Reads happen with
// capture mode OFF, so they are real reads.
bool memMatchesCapture(const EeDiffStore& s, u64& real_out)
{
switch (s.bits)
{
case 8: real_out = memRead8(s.addr); return real_out == (s.lo & 0xffu);
case 16: real_out = memRead16(s.addr); return real_out == (s.lo & 0xffffu);
case 32: real_out = memRead32(s.addr); return real_out == (s.lo & 0xffffffffu);
case 64: real_out = memRead64(s.addr); return real_out == s.lo;
case 128:
{
u128 v;
memRead128(s.addr, &v);
real_out = v.lo; // report low half; compare both
return v.lo == s.lo && v.hi == s.hi;
}
default: real_out = 0; return true;
}
}
// True iff the effective address lands in EE main RAM (32 MB, incl. KSEG0/KSEG1 mirrors) or
// the 16 KB scratchpad — the ONLY regions where "read the value back and compare it to what
// the interpreter would have written" is a valid store check. Everything else is memory-mapped
// I/O: EE registers 0x10000000-0x1000FFFF (DMAC/GIF/VIF/IPU/timers/INTC), GS privileged
// registers 0x12000000, VU/GS mem, BIOS ROM. A read of those does NOT return the last written
// value, so comparing a store there against a read-back is a GUARANTEED FALSE POSITIVE — and
// re-running such an access on the interpreter is unsafe (DMA kicks, counter/event side effects,
// Cpu->CancelInstruction longjmps). The texture-decompression bug we hunt writes to RAM, so
// RAM + scratchpad is exactly — and only — the region we verify.
inline bool eeDiffAddrIsRam(u32 addr)
{
if ((addr & 0xFFFFC000u) == 0x70000000u) // scratchpad (0x70000000, 16 KB)
return true;
return (addr & 0x1FFFFFFFu) < 0x02000000u; // main RAM (0x00000000, 32 MB) + KSEG0/KSEG1 mirrors
}
// A memory op whose effective address is NOT RAM/scratchpad must be SKIPPED entirely: the
// interpreter re-run risks event-test/longjmp/DMA-kick side effects, and the store-compare
// would be a false positive (I/O doesn't read back what you wrote). Only RAM/scratchpad
// accesses are verified. Effective address = GPR[rs].UL[0] + s16(imm) (standard EE base+offset;
// LWL/SWL/LQ/SQ mask low bits but stay in the same region, so the RAM test still holds).
// Returns true = "skip".
bool opTouchesNonRam(u32 op, const EeDiffRegs& pre)
{
const u32 primary = op >> 26;
bool is_mem;
switch (primary)
{
case 0x1e: // LQ
case 0x1f: // SQ
case 0x20: case 0x21: case 0x22: case 0x23: // LB LH LWL LW
case 0x24: case 0x25: case 0x26: case 0x27: // LBU LHU LWR LWU
case 0x28: case 0x29: case 0x2a: case 0x2b: // SB SH SWL SW
case 0x2c: case 0x2d: case 0x2e: case 0x2f: // SDL SDR SWR CACHE
case 0x1a: case 0x1b: // LDL LDR
case 0x37: case 0x3f: // LD SD
is_mem = true;
break;
default:
is_mem = false;
break;
}
if (!is_mem)
return false;
const u32 rs = (op >> 21) & 0x1f;
const u32 addr = pre.gpr[rs].UL[0] + static_cast<u32>(static_cast<s32>(static_cast<s16>(op)));
return !eeDiffAddrIsRam(addr);
}
// Ops whose interpreter re-run would raise a CPU exception: SYSCALL/BREAK and the conditional
// TRAPs. The interpreter services these via cpuException -> CP0 mutation + a longjmp we neither
// snapshot (no CP0 in EeDiffRegs) nor can survive mid-block. The rec ends the block on these
// anyway, so they carry no straight-line divergence to check. Skip the re-run. (Trapping-arith
// signed-overflow is handled separately by opWouldTrapOverflow.)
bool opRaisesException(u32 op)
{
const u32 primary = op >> 26;
if (primary == 0x00) // SPECIAL
{
const u32 funct = op & 0x3f;
if (funct == 0x0c || funct == 0x0d) return true; // SYSCALL, BREAK
if (funct >= 0x30 && funct <= 0x36) return true; // TGE TGEU TLT TLTU TEQ (.34) TNE (.36)
return false;
}
if (primary == 0x01) // REGIMM
{
const u32 rt = (op >> 16) & 0x1f;
return (rt >= 0x08 && rt <= 0x0e); // TGEI TGEIU TLTI TLTIU TEQI TNEI
}
return false;
}
// The EE's trapping arithmetic (ADD/ADDI/SUB/DADD/DADDI/DSUB) raises a signed-overflow
// exception in the INTERPRETER (cpuException -> mutates CP0 + pc, possibly a longjmp), but
// the recompiler intentionally SKIPS that trap (treats them as ADDU/…, matching the x86
// JIT — see aR5900Arith.cpp). So on a real overflow they legitimately diverge and re-running
// the interpreter would corrupt CP0 irreversibly (we don't snapshot CP0). Detect overflow
// from the pre-op operands (mirroring _add32_Overflow/_add64_Overflow exactly) and SKIP the
// re-run when it would trap. The far-more-common non-overflow path is still fully verified.
// Returns true = "skip this op (would trap)".
bool add32WouldOverflow(s32 x, s32 y)
{
GPR_reg64 r;
r.SD[0] = static_cast<s64>(x) + y;
return (r.UL[0] >> 31) != (r.UL[1] & 1);
}
bool add64WouldOverflow(s64 x, s64 y)
{
const s64 result = x + y;
return ((~(x ^ y)) & (x ^ result)) < 0;
}
bool opWouldTrapOverflow(u32 op, const EeDiffRegs& pre)
{
const u32 primary = op >> 26;
const u32 rs = (op >> 21) & 0x1f;
const u32 rt = (op >> 16) & 0x1f;
const s32 imm = static_cast<s16>(op);
const s64 srs = pre.gpr[rs].SD[0];
const s64 srt = pre.gpr[rt].SD[0];
switch (primary)
{
case 0x08: return add32WouldOverflow(static_cast<s32>(srs), imm); // ADDI
case 0x18: return add64WouldOverflow(srs, imm); // DADDI
case 0x00: // SPECIAL — funct disambiguates the trapping R-type adds/subs
switch (op & 0x3f)
{
case 0x20: return add32WouldOverflow(static_cast<s32>(srs), static_cast<s32>(srt)); // ADD
case 0x22: return add32WouldOverflow(static_cast<s32>(srs), static_cast<s32>(-srt)); // SUB
case 0x2c: return add64WouldOverflow(srs, srt); // DADD
case 0x2e: return add64WouldOverflow(srs, -srt); // DSUB
default: return false;
}
default: return false;
}
}
void reportDivergence(u32 pc, u32 op, const char* what,
const char* detail, u64 rec_val, u64 interp_val)
{
const u32 primary = op >> 26;
const u32 rs = (op >> 21) & 0x1f;
const u32 rt = (op >> 16) & 0x1f;
const u32 rd = (op >> 11) & 0x1f;
const u32 sa = (op >> 6) & 0x1f;
const u32 funct = op & 0x3f;
const char* name = ::R5900::GetInstruction(op).Name;
Console.WriteLn(
"@@EEDIFF@@ pc=%08x op=%08x %-8s DIVERGE %s(%s) rec=%016llx interp=%016llx "
"| primary=%02x funct=%02x rs=%u rt=%u rd=%u sa=%u",
pc, op, name, what, detail,
static_cast<unsigned long long>(rec_val),
static_cast<unsigned long long>(interp_val),
primary, funct, rs, rt, rd, sa);
}
} // namespace
// --------------------------------------------------------------------------------------
// Store capture (called from vtlb_memWrite hook)
// --------------------------------------------------------------------------------------
void eeDiffCaptureStore(u32 addr, u32 bits, u64 lo, u64 hi)
{
if (g_diff_store_count >= EEDIFF_MAX_STORES)
return; // shouldn't happen for one op; drop extras defensively
EeDiffStore& s = g_diff_stores[g_diff_store_count++];
s.addr = addr;
s.bits = bits;
s.lo = lo;
s.hi = hi;
}
// --------------------------------------------------------------------------------------
// Emitted-code entry points
// --------------------------------------------------------------------------------------
extern "C" void eeDiffSnapshotPre()
{
snapshotInto(g_diff_pre);
}
extern "C" void eeDiffVerify(u32 pc, u32 op)
{
// The recompiled op has just run: cpuRegs == REC-post. Save it first so we can always
// restore it (the rec owns guest state from here on).
snapshotInto(g_diff_recpost);
// Skip memory ops whose effective address is not RAM/scratchpad: the interpreter re-run
// would touch memory-mapped I/O (event test / DMA kick / longjmp risk) and the store-compare
// there is a false positive. cpuRegs is already REC-post; nothing to do. See opTouchesNonRam.
if (opTouchesNonRam(op, g_diff_pre))
return;
// Skip ops whose interpreter re-run would raise a CPU exception (SYSCALL/BREAK/TRAP) — the
// longjmp would escape mid-block and we don't snapshot CP0. See opRaisesException.
if (opRaisesException(op))
return;
// Skip trapping-arithmetic ops that would raise a signed-overflow exception in the
// interpreter (the rec deliberately doesn't trap — a legitimate, known divergence that
// would also corrupt CP0 in the re-run). See opWouldTrapOverflow.
if (opWouldTrapOverflow(op, g_diff_pre))
return;
restoreFrom(g_diff_pre); // cpuRegs = interpreter input (op-entry state)
g_diff_store_count = 0;
const u32 saved_code = cpuRegs.code;
cpuRegs.code = op; // the interpreter's operand macros (_Rs_/_Rt_/_Imm_/...) read this
g_ee_diff_capture_stores = true;
::R5900::GetInstruction(op).interpret(); // one op; stores captured, not applied
g_ee_diff_capture_stores = false;
cpuRegs.code = saved_code;
// cpuRegs is now INTERP-post (regs updated in place; stores diverted to the log).
bool diverged = false;
// (i) compare GPRs (full 128-bit), then HI, LO.
if (g_diff_reported < EEDIFF_MAX_REPORTS)
{
for (u32 r = 0; r < 32 && !diverged; r++)
{
const GPR_reg& ri = cpuRegs.GPR.r[r]; // interp-post
const GPR_reg& rr = g_diff_recpost.gpr[r]; // rec-post
if (ri.UD[0] != rr.UD[0] || ri.UD[1] != rr.UD[1])
{
char detail[24];
std::snprintf(detail, sizeof(detail), "GPR%u.lo", r);
reportDivergence(pc, op, "reg", detail, rr.UD[0], ri.UD[0]);
if (ri.UD[1] != rr.UD[1])
reportDivergence(pc, op, "reg", "GPRhi", rr.UD[1], ri.UD[1]);
diverged = true;
}
}
if (!diverged && (cpuRegs.HI.UD[0] != g_diff_recpost.hi.UD[0] ||
cpuRegs.HI.UD[1] != g_diff_recpost.hi.UD[1]))
{
reportDivergence(pc, op, "reg", "HI", g_diff_recpost.hi.UD[0], cpuRegs.HI.UD[0]);
diverged = true;
}
if (!diverged && (cpuRegs.LO.UD[0] != g_diff_recpost.lo.UD[0] ||
cpuRegs.LO.UD[1] != g_diff_recpost.lo.UD[1]))
{
reportDivergence(pc, op, "reg", "LO", g_diff_recpost.lo.UD[0], cpuRegs.LO.UD[0]);
diverged = true;
}
// (ii) compare each captured interpreter store against the real memory the rec
// already wrote. Read memory with capture mode OFF (real reads).
for (u32 i = 0; i < g_diff_store_count && !diverged; i++)
{
const EeDiffStore& s = g_diff_stores[i];
if (!eeDiffAddrIsRam(s.addr))
continue; // 2nd-layer guard: never compare an I/O store against a read-back
u64 real_val = 0;
if (!memMatchesCapture(s, real_val))
{
char detail[40];
std::snprintf(detail, sizeof(detail), "mem[%08x]/%ub", s.addr, s.bits);
reportDivergence(pc, op, "mem", detail, real_val, s.lo);
diverged = true;
}
}
if (diverged)
g_diff_reported++;
}
// CRITICAL: restore cpuRegs to REC-post so the real recompiled run is unaffected —
// the recompiler owns guest state and continues from here.
restoreFrom(g_diff_recpost);
cpuRegs.code = saved_code;
}
-63
View File
@@ -1,63 +0,0 @@
// SPDX-License-Identifier: GPL-3.0+
//
// @@EEDIFF@@ THROWAWAY DIAGNOSTIC — EE recompiler-vs-interpreter differential verifier.
//
// Purpose: pin the exact ARM64 EE guest instruction whose recompiled result diverges
// from the C++ interpreter. Built to hunt the True Crime NYC (SLUS-21106) texture
// decompressor corruption (displaced paletted texture bytes) that GS-dump replay
// proved is an EE data-gen bug, not the renderer.
//
// This whole feature is gated behind g_ee_diff_verify (default false). When it is
// false there is ZERO overhead — no hooks are emitted into recompiled blocks, and the
// store-capture branch in vtlb_memWrite is a single never-taken bool test. Flip it on
// (Recompiler tab -> "EE Diff Verify (diag)") and the EE block cache is cleared so
// blocks recompile WITH the per-op verify hooks.
//
// How it works (see EEDiffVerify.cpp for detail):
// * The recompiler, when compiling a straight-line op through the native generators
// (recTranslateOp), emits around each op: snapshot cpuRegs -> real op -> verify.
// * eeDiffVerify() re-runs that ONE op on the C++ interpreter from the pre-op
// snapshot, with interpreter stores CAPTURED (recorded, not applied — the rec
// already wrote real memory), then compares the interpreter's post-state (regs +
// each captured store vs the real memory the rec wrote) against the rec's post
// state. First mismatch logs "@@EEDIFF@@ ... DIVERGE ...".
//
// Everything here is wrapped with // @@EEDIFF@@ so it is trivially greppable/revertable.
#pragma once
#include "common/Pcsx2Defs.h"
// Master enable. Set via the Recompiler-tab toggle -> NativeApp.setEeDiffVerify() ->
// eeDiffSetEnabled(). Read at recompile time (to decide whether to emit hooks) and by
// the vtlb store-capture fast-out. `volatile` because it is toggled from the UI thread
// while the EE thread reads it; the block-cache clear that the setter forces is the
// real synchronisation point.
extern volatile bool g_ee_diff_verify;
// Store-capture mode. Set to true ONLY for the brief window while eeDiffVerify re-runs
// the interpreter op; vtlb_memWrite* checks it and records {addr,size,value} into the
// capture log instead of touching real memory. Never true outside eeDiffVerify.
extern bool g_ee_diff_capture_stores;
// Record one interpreter store while g_ee_diff_capture_stores is set. Called from the
// vtlb_memWrite<T> / vtlb_memWrite128 hook. `bits` = 8/16/32/64/128. For 128-bit the
// value is passed as two u64 halves (lo, hi); narrower sizes pass the value in lo.
void eeDiffCaptureStore(u32 addr, u32 bits, u64 lo, u64 hi);
// Emitted-code entry points (called from recompiled blocks — plain C ABI, no args
// except pc/op which the rec bakes in as immediates).
extern "C" {
// Snapshot the whole guest register file (GPR[0..31], HI, LO, PC, sa) into g_diff_pre.
// Emitted BEFORE the real recompiled op runs.
void eeDiffSnapshotPre();
// Re-run `op` on the interpreter from g_diff_pre with stores captured, then compare
// against the rec's post-state (current cpuRegs + real memory). Emitted AFTER the op.
void eeDiffVerify(u32 pc, u32 op);
}
// UI/JNI setter: set the enable flag. Returns nothing; the caller (native-lib JNI) is
// responsible for also clearing the EE block cache so blocks recompile with/without the
// hooks. Kept separate so the header has no dependency on the recompiler internals.
void eeDiffSetEnabled(bool enabled);
bool eeDiffGetEnabled();
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "صوت SPU2 SIMD (تجريبي)",
"audio.spu2Simd.description": "مسار NEON سريع لمعالجة صوت الصدى (reverb) — يوفّر المعالج، مما قد يحسّن الأداء على الأجهزة المحدودة المعالج. الإيقاف (الافتراضي) يستخدم المسار القياسي بصوت غير معدّل. أعد تشغيل اللعبة للتبديل.",
"jit.recompiler.warning": "تعطيل أي recompiler يُسقط ذلك المعالج/COP إلى مُفسّره — أبطأ بكثير، للتصحيح فقط. تُطبَّق التغييرات على اللعبة الجارية.",
"jit.diagnostics.header": "التشخيص",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.eeDiffVerify.description": "فحص تفاضلي بين recompiler والمُفسّر لـ EE. يسجّل أول تعليمة خاطئة الترجمة. تباطؤ كبير؛ متوقف افتراضياً.",
"action.no": "لا",
"action.restore": "استعادة",
"action.yes": "نعم",
@@ -322,9 +322,6 @@
"info.serial": "Seriennummer",
"info.setCover": "Cover festlegen",
"info.title": "Name",
"jit.diagnostics.header": "Diagnose",
"jit.eeDiffVerify.description": "Differenzprüfung Recompiler vs. Interpreter für die EE. Protokolliert die erste fehlkompilierte Instruktion. Starke Verlangsamung; standardmäßig aus.",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.recompiler.warning": "Ein deaktivierter Recompiler wirft die jeweilige CPU/COP auf ihren Interpreter zurück — deutlich langsamer, nur zum Debuggen. Änderungen gelten für das laufende Spiel.",
"memcard.cancelNew": "Neu abbrechen",
"memcard.cardName.label": "Kartenname (A zum Tippen)",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Audio SPU2 SIMD (experimental)",
"audio.spu2Simd.description": "Ruta rápida NEON para el procesamiento de reverb — libera CPU, lo que puede ayudar en dispositivos limitados por CPU. Off (por defecto) usa la ruta estándar con audio sin cambios. Reinicia el juego para cambiar.",
"jit.recompiler.warning": "Desactivar un recompilador pasa esa CPU/COP a su intérprete — mucho más lento, solo para depuración. Los cambios se aplican al juego en ejecución.",
"jit.diagnostics.header": "Diagnósticos",
"jit.eeDiffVerify.label": "Verificación diferencial EE",
"jit.eeDiffVerify.description": "Comprobación diferencial recompilador-vs-intérprete para el EE. Registra la primera instrucción mal compilada. Ralentización fuerte; off por defecto.",
"action.no": "No",
"action.restore": "RESTAURAR",
"action.yes": "Sí",
@@ -101,9 +101,6 @@
"audio.spu2Simd.label": "صدای SPU2 SIMD (تجربی)",
"audio.spu2Simd.description": "مسیر سریع نئون برای پردازش صدای Reverb - CPU را آزاد می‌کند، که می‌تواند به عملکرد دستگاه‌های دارای CPU محدود کمک کند. خاموش (پیش‌فرض) از مسیر استاندارد با صدای بدون تغییر استفاده می‌کند. برای تعویض، بازی را ریبوت کنید.",
"jit.recompiler.warning": "غیرفعال کردن یک کامپایلر، آن CPU/COP را روی مفسر آن می‌اندازد - بسیار کندتر، فقط برای اشکال‌زدایی. تغییرات در بازی در حال اجرا اعمال می شود.",
"jit.diagnostics.header": "تشخیص",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.eeDiffVerify.description": "بررسی تفاضل کامپایلر در مقابل مفسر برای EE. اولین دستور کامپایل اشتباه را ثبت می کند. کندی شدید؛ به طور پیش فرض خاموش است",
"action.no": "خیر",
"action.restore": "بازیابی",
"action.yes": "بله",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Audio SPU2 SIMD (expérimental)",
"audio.spu2Simd.description": "Chemin rapide NEON pour le traitement de la réverbération — libère du CPU, ce qui peut aider les appareils limités par le CPU. Désactivé (par défaut) utilise le chemin standard avec un audio inchangé. Redémarrez le jeu pour changer.",
"jit.recompiler.warning": "Désactiver un recompiler bascule ce CPU/COP sur son interpréteur — bien plus lent, pour le débogage uniquement. Les changements s'appliquent au jeu en cours.",
"jit.diagnostics.header": "Diagnostics",
"jit.eeDiffVerify.label": "Vérif. diff EE",
"jit.eeDiffVerify.description": "Vérification différentielle recompiler-vs-interpréteur pour l'EE. Journalise la première instruction mal compilée. Ralentissement important ; désactivé par défaut.",
"action.no": "Non",
"action.restore": "RESTAURER",
"action.yes": "Oui",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Audio SPU2 SIMD (eksperimental)",
"audio.spu2Simd.description": "Jalur cepat NEON untuk pemrosesan audio reverb — melegakan CPU, yang dapat membantu performa pada perangkat terbatas CPU. Off (default) memakai jalur standar dengan audio tak berubah. Reboot game untuk berganti.",
"jit.recompiler.warning": "Menonaktifkan recompiler menjatuhkan CPU/COP itu ke interpreternya — jauh lebih lambat, hanya untuk debugging. Perubahan berlaku pada game yang sedang berjalan.",
"jit.diagnostics.header": "Diagnostik",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.eeDiffVerify.description": "Pemeriksaan diferensial recompiler-vs-interpreter untuk EE. Mencatat instruksi salah-kompilasi pertama. Melambat berat; off secara default.",
"action.no": "Tidak",
"action.restore": "PULIHKAN",
"action.yes": "Ya",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Audio SPU2 SIMD (sperimentale)",
"audio.spu2Simd.description": "Percorso rapido NEON per l'elaborazione del riverbero — libera CPU, utile su dispositivi limitati dalla CPU. Off (predefinito) usa il percorso standard con audio invariato. Riavvia il gioco per cambiare.",
"jit.recompiler.warning": "Disabilitare un recompiler passa quel CPU/COP al suo interprete — molto più lento, solo per il debug. Le modifiche si applicano al gioco in esecuzione.",
"jit.diagnostics.header": "Diagnostica",
"jit.eeDiffVerify.label": "Verifica diff EE",
"jit.eeDiffVerify.description": "Controllo differenziale recompiler-vs-interprete per l'EE. Registra la prima istruzione mal compilata. Rallentamento pesante; off per impostazione predefinita.",
"action.no": "No",
"action.restore": "RIPRISTINA",
"action.yes": "Sì",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "SPU2 SIMDオーディオ(実験的)",
"audio.spu2Simd.description": "リバーブ音声処理のNEON高速パス — CPUを解放し、CPU制約のあるデバイスでパフォーマンス向上に役立ちます。オフ(デフォルト)は音声が変わらない標準パスを使用します。切り替えにはゲームの再起動が必要です。",
"jit.recompiler.warning": "recompilerを無効にするとそのCPU/COPがインタプリタで動作します — かなり遅く、デバッグ専用です。変更は実行中のゲームに適用されます。",
"jit.diagnostics.header": "診断",
"jit.eeDiffVerify.label": "EE差分検証",
"jit.eeDiffVerify.description": "EEのrecompilerとインタプリタの差分チェック。最初にコンパイルがずれた命令を記録します。大幅に低速化。デフォルトはオフ。",
"action.no": "いいえ",
"action.restore": "復元",
"action.yes": "はい",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "SPU2 SIMD 오디오 (실험적)",
"audio.spu2Simd.description": "리버브 오디오 처리를 위한 NEON 고속 경로 — CPU를 아껴 CPU 제약 기기에서 성능에 도움이 될 수 있습니다. 끔(기본값)은 오디오가 그대로인 표준 경로를 사용합니다. 전환하려면 게임을 재시작하세요.",
"jit.recompiler.warning": "리컴파일러를 끄면 해당 CPU/COP가 인터프리터로 전환됩니다 — 훨씬 느리며 디버깅용입니다. 변경 사항은 실행 중인 게임에 적용됩니다.",
"jit.diagnostics.header": "진단",
"jit.eeDiffVerify.label": "EE 차이 검증",
"jit.eeDiffVerify.description": "EE의 리컴파일러 대 인터프리터 차이 검사입니다. 첫 오컴파일 명령을 기록합니다. 크게 느려지며 기본값은 끔입니다.",
"action.no": "아니오",
"action.restore": "복원",
"action.yes": "예",
@@ -97,9 +97,6 @@
"audio.spu2Simd.label": "Dengê SPU2 SIMD (ceribandinî)",
"audio.spu2Simd.description": "Rêya bilez a NEON ji bo pêvajoyek dengî ya reverb - CPU azad dike, ku dikare alîkariya performansê li ser cîhazên bi CPU-sînordar bike. Off (default) riya standard bi dengê neguhêrbar bikar tîne. Ji nû ve lîstikê ji nû ve bidin destpêkirin.",
"jit.recompiler.warning": "Neçalakkirina ji nûvesazkerê wê CPU/COP davêje ser wergêrê wê - pir hêdîtir, tenê ji bo xeletkirinê. Guhertin di lîstika xebitandinê de derbas dibin.",
"jit.diagnostics.header": "Diagnostics",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.eeDiffVerify.description": "Ji bo EE-yê kontrolkirina cûdahiya Recompiler-vs-wergêr. Yekem talîmata çewtkompêlkirinê tomar dike. Hêdî hêdî hêdî; off by default.",
"action.no": "No",
"action.restore": "NÛVDEKIRIN",
"action.yes": "Erê",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Dźwięk SPU2 SIMD (eksperymentalne)",
"audio.spu2Simd.description": "Szybka ścieżka NEON do przetwarzania pogłosu — odciąża CPU, co może pomóc na urządzeniach ograniczonych CPU. Wyłączone (domyślnie) używa standardowej ścieżki z niezmienionym dźwiękiem. Zrestartuj grę, aby przełączyć.",
"jit.recompiler.warning": "Wyłączenie recompilera przełącza dany CPU/COP na interpreter — dużo wolniej, tylko do debugowania. Zmiany stosują się do działającej gry.",
"jit.diagnostics.header": "Diagnostyka",
"jit.eeDiffVerify.label": "Weryfikacja różnic EE",
"jit.eeDiffVerify.description": "Różnicowa kontrola recompiler-vs-interpreter dla EE. Loguje pierwszą źle skompilowaną instrukcję. Duże spowolnienie; domyślnie wyłączone.",
"action.no": "Nie",
"action.restore": "PRZYWRÓĆ",
"action.yes": "Tak",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Áudio SPU2 SIMD (experimental)",
"audio.spu2Simd.description": "Caminho rápido NEON para o processamento de reverb — libera CPU, o que pode ajudar o desempenho em aparelhos limitados por CPU. Desligado (padrão) usa o caminho normal com áudio inalterado. Reinicie o jogo para trocar.",
"jit.recompiler.warning": "Desativar um recompilador joga aquela CPU/COP no interpretador — muito mais lento, só para depuração. As mudanças se aplicam ao jogo em execução.",
"jit.diagnostics.header": "Diagnóstico",
"jit.eeDiffVerify.label": "Verificação Diff EE",
"jit.eeDiffVerify.description": "Comparação recompilador-vs-interpretador para o EE. Registra a primeira instrução mal compilada. Lentidão pesada; desligado por padrão.",
"action.no": "Não",
"action.restore": "RESTAURAR",
"action.yes": "Sim",
@@ -97,9 +97,6 @@
"audio.spu2Simd.label": "Звук SPU2 SIMD (экспериментальный)",
"audio.spu2Simd.description": "Быстрый путь NEON для обработки звука реверберацией — освобождает ЦП, что может повысить производительность на устройствах с ограниченным количеством ЦП. Выкл. (по умолчанию) используется стандартный путь с неизмененным звуком. Перезагрузите игру, чтобы переключиться.",
"jit.recompiler.warning": "Отключение рекомпилятора передает этот процессор/COP на его интерпретатор — гораздо медленнее, только для отладки. Изменения касаются запущенной игры.",
"jit.diagnostics.header": "Диагностика",
"jit.eeDiffVerify.label": "EE разница проверить",
"jit.eeDiffVerify.description": "Дифференциальная проверка рекомпилятора и интерпретатора для EE. Регистрирует первую инструкцию с ошибкой компиляции. Сильное замедление; выключен по умолчанию.",
"action.no": "Нет",
"action.restore": "ВОССТАНОВИТЬ",
"action.yes": "Да",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "เสียง SPU2 SIMD (ทดลอง)",
"audio.spu2Simd.description": "เส้นทางเร็ว NEON สำหรับประมวลผลเสียง reverb — ช่วยลดภาระ CPU ซึ่งช่วยเพิ่มประสิทธิภาพบนเครื่องที่ CPU จำกัด ปิด (ค่าเริ่มต้น) ใช้เส้นทางมาตรฐานโดยเสียงไม่เปลี่ยน รีบูตเกมเพื่อสลับ",
"jit.recompiler.warning": "การปิด recompiler จะทำให้ CPU/COP นั้นตกไปใช้ interpreter — ช้ากว่ามาก สำหรับดีบักเท่านั้น การเปลี่ยนแปลงมีผลกับเกมที่กำลังรัน",
"jit.diagnostics.header": "การวินิจฉัย",
"jit.eeDiffVerify.label": "EE Diff Verify",
"jit.eeDiffVerify.description": "การตรวจเทียบ recompiler-กับ-interpreter สำหรับ EE บันทึกคำสั่งแรกที่คอมไพล์ผิด ช้าลงมาก ปิดโดยค่าเริ่มต้น",
"action.no": "ไม่",
"action.restore": "กู้คืน",
"action.yes": "ใช่",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "SPU2 SIMD ses (deneysel)",
"audio.spu2Simd.description": "Reverb ses işleme için NEON hızlı yolu — CPU'yu serbest bırakır, CPU kısıtlı cihazlarda performansa yardımcı olabilir. Kapalı (varsayılan) sesi değiştirmeden standart yolu kullanır. Değiştirmek için oyunu yeniden başlatın.",
"jit.recompiler.warning": "Bir recompiler'ı devre dışı bırakmak o CPU/COP'u kendi yorumlayıcısına düşürür — çok daha yavaş, yalnızca hata ayıklama için. Değişiklikler çalışan oyuna uygulanır.",
"jit.diagnostics.header": "Tanılama",
"jit.eeDiffVerify.label": "EE Diff Doğrulama",
"jit.eeDiffVerify.description": "EE için recompiler-yorumlayıcı fark kontrolü. İlk yanlış derlenen komutu kaydeder. Ağır yavaşlama; varsayılan olarak kapalı.",
"action.no": "Hayır",
"action.restore": "GERİ YÜKLE",
"action.yes": "Evet",
@@ -97,9 +97,6 @@
"audio.spu2Simd.label": "Аудіо SPU2 SIMD (експериментальний)",
"audio.spu2Simd.description": "Швидкий шлях NEON для обробки аудіо реверберації — звільняє центральний процесор, що може підвищити продуктивність на пристроях з обмеженим процесором. Вимк. (за замовчуванням) використовує стандартний шлях із незмінним звуком. Перезавантажте гру, щоб переключитися.",
"jit.recompiler.warning": "Вимкнення рекомпілятора скидає ЦП/COP на його інтерпретатор — набагато повільніше, лише для налагодження. Зміни стосуються запущеної гри.",
"jit.diagnostics.header": "діагностика",
"jit.eeDiffVerify.label": "Перевірка EE Diff",
"jit.eeDiffVerify.description": "Диференціальна перевірка рекомпілятора проти інтерпретатора для EE. Записує першу інструкцію неправильної компіляції. Сильне уповільнення; за замовчуванням вимкнено.",
"action.no": "немає",
"action.restore": "ВІДНОВИТИ",
"action.yes": "так",
@@ -58,9 +58,6 @@
"audio.spu2Simd.label": "Âm thanh SPU2 SIMD (thử nghiệm)",
"audio.spu2Simd.description": "Đường xử lý NEON nhanh cho xử lý âm thanh reverb — giải phóng CPU, có thể cải thiện hiệu năng trên thiết bị hạn chế CPU. Tắt (mặc định) dùng đường xử lý tiêu chuẩn, âm thanh không đổi. Khởi động lại game để chuyển đổi.",
"jit.recompiler.warning": "Tắt một recompiler sẽ đẩy CPU/COP đó về trình thông dịch — chậm hơn nhiều, chỉ để gỡ lỗi. Thay đổi áp dụng cho game đang chạy.",
"jit.diagnostics.header": "Chẩn đoán",
"jit.eeDiffVerify.label": "Kiểm tra EE Diff",
"jit.eeDiffVerify.description": "Kiểm tra so sánh recompiler với trình thông dịch cho EE. Ghi log lệnh biên dịch sai đầu tiên. Chậm nhiều; mặc định tắt.",
"action.no": "Không",
"action.restore": "KHÔI PHỤC",
"action.yes": "Có",

Some files were not shown because too many files have changed in this diff Show More