Compare commits

...

4 Commits

Author SHA1 Message Date
Ty Lamontagne
16b1095a7b EE Cache: Shrink tag size by 4 bytes 2025-01-08 18:34:30 -05:00
Silent
3b5b3ffa91 Patch: Re-run PPT_ONCE_ON_LOAD patches when enabling them as the game is running 2025-01-08 18:30:51 -05:00
Silent
7ebcca36d2 Patch: Actually apply type 2 patches on the entry point
Type 2 patches were supposed to be "Type 0 + Type 1",
but in reality they only executed on vblank, making them equivalent
to Type 1.
2025-01-08 18:30:51 -05:00
PCSX2 Bot
501c543d1b [ci skip] Qt: Update Base Translation. 2025-01-08 19:46:56 +01:00
5 changed files with 74 additions and 24 deletions

View File

@@ -16514,7 +16514,7 @@ The saves will not be recoverable.</source>
<name>MemoryCard</name>
<message>
<location filename="../../pcsx2/SIO/Memcard/MemoryCardFile.cpp" line="282"/>
<location filename="../../pcsx2/SIO/Memcard/MemoryCardFile.cpp" line="967"/>
<location filename="../../pcsx2/SIO/Memcard/MemoryCardFile.cpp" line="969"/>
<source>Memory Card Creation Failed</source>
<translation type="unfinished"></translation>
</message>
@@ -16547,7 +16547,7 @@ Close any other instances of PCSX2, or restart your computer.
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/SIO/Memcard/MemoryCardFile.cpp" line="968"/>
<location filename="../../pcsx2/SIO/Memcard/MemoryCardFile.cpp" line="970"/>
<source>Failed to create memory card. The error was:
{}</source>
<translation type="unfinished"></translation>

View File

@@ -23,10 +23,11 @@ namespace
// When this happens, the cache still fills with the data and when it gets evicted the data is lost.
// We don't emulate memory access on a logic level, so we need to ensure that we don't try to load/store to a non-existant physical address.
// This fixes the Find My Own Way demo.
bool validPFN = true;
// The lower parts of a cache tags structure is as follows:
// 31 - 12: The physical address cache tag.
// 11 - 7: Unused.
// 11: Used by PCSX2 to indicate if the physical address is valid.
// 10 - 7: Unused.
// 6: Dirty flag.
// 5: Valid flag.
// 4: LRF flag - least recently filled flag.
@@ -39,7 +40,8 @@ namespace
VALID_FLAG = 0x20,
LRF_FLAG = 0x10,
LOCK_FLAG = 0x8,
ALL_FLAGS = 0xFFF
ALL_FLAGS = 0x7FF,
ALL_BITS = 0xFFF
};
int flags() const
@@ -65,23 +67,36 @@ namespace
void clearLocked() { rawValue &= ~LOCK_FLAG; }
void toggleLRF() { rawValue ^= LRF_FLAG; }
uptr addr() const { return rawValue & ~ALL_FLAGS; }
uptr addr() const { return rawValue & ~ALL_BITS; }
void setAddr(uptr addr)
{
rawValue &= ALL_FLAGS;
rawValue |= (addr & ~ALL_FLAGS);
rawValue &= ALL_BITS;
rawValue |= (addr & ~ALL_BITS);
}
bool matches(uptr other) const
{
return isValid() && addr() == (other & ~ALL_FLAGS);
return isValid() && addr() == (other & ~ALL_BITS);
}
void clear()
{
rawValue &= LRF_FLAG;
}
constexpr bool isValidPFN() const
{
return rawValue & 0x800;
}
constexpr void setValidPFN(bool valid)
{
if (valid)
rawValue |= 0x800;
else
rawValue &= ~0x800;
}
};
struct CacheLine
@@ -103,7 +118,7 @@ namespace
uptr target = addr();
CACHE_LOG("Write back at %zx", target);
if (tag.validPFN)
if (tag.isValidPFN())
*reinterpret_cast<CacheData*>(target) = data;
tag.clearDirty();
}
@@ -113,7 +128,7 @@ namespace
pxAssertMsg(!tag.isDirtyAndValid(), "Loaded a value into cache without writing back the old one!");
tag.setAddr(ppf);
if (!tag.validPFN)
if (!tag.isValidPFN())
{
// Reading from invalid physical addresses seems to return 0 on hardware
std::memset(&data, 0, sizeof(data));
@@ -238,7 +253,7 @@ static int getFreeCache(u32 mem, int* way, bool validPFN)
CacheLine line = cache.lineAt(setIdx, newWay);
line.writeBackIfNeeded();
line.tag.validPFN = validPFN;
line.tag.setValidPFN(validPFN);
line.load(ppf);
line.tag.toggleLRF();
}

View File

@@ -156,7 +156,7 @@ namespace Patch
static bool PatchStringHasUnlabelledPatch(const std::string& pnach_data);
static void ExtractPatchInfo(PatchInfoList* dst, const std::string& pnach_data, u32* num_unlabelled_patches);
static void ReloadEnabledLists();
static u32 EnablePatches(const PatchList& patches, const EnablePatchList& enable_list);
static u32 EnablePatches(const PatchList& patches, const EnablePatchList& enable_list, const EnablePatchList& enable_immediately_list);
static void ApplyPatch(const PatchCommand* p);
static void ApplyDynaPatch(const DynamicPatch& patch, u32 address);
@@ -183,6 +183,8 @@ namespace Patch
static std::vector<DynamicPatch> s_active_pnach_dynamic_patches;
static EnablePatchList s_enabled_cheats;
static EnablePatchList s_enabled_patches;
static EnablePatchList s_just_enabled_cheats;
static EnablePatchList s_just_enabled_patches;
static u32 s_patches_crc;
static std::optional<AspectRatioType> s_override_aspect_ratio;
static std::optional<GSInterlaceMode> s_override_interlace_mode;
@@ -583,13 +585,13 @@ std::string Patch::GetPnachFilename(const std::string_view serial, u32 crc, bool
void Patch::ReloadEnabledLists()
{
const EnablePatchList prev_enabled_cheats = std::move(s_enabled_cheats);
if (EmuConfig.EnableCheats && !Achievements::IsHardcoreModeActive())
s_enabled_cheats = Host::GetStringListSetting(CHEATS_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY);
else
s_enabled_cheats = {};
s_enabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY);
const EnablePatchList prev_enabled_patches = std::exchange(s_enabled_patches, Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_ENABLE_CONFIG_KEY));
const EnablePatchList disabled_patches = Host::GetStringListSetting(PATCHES_CONFIG_SECTION, PATCH_DISABLE_CONFIG_KEY);
// Name based matching for widescreen/NI settings.
@@ -621,10 +623,29 @@ void Patch::ReloadEnabledLists()
++it;
}
}
s_just_enabled_cheats.clear();
s_just_enabled_patches.clear();
for (const auto& p : s_enabled_cheats)
{
if (std::find(prev_enabled_cheats.begin(), prev_enabled_cheats.end(), p) == prev_enabled_cheats.end())
{
s_just_enabled_cheats.emplace_back(p);
}
}
for (const auto& p : s_enabled_patches)
{
if (std::find(prev_enabled_patches.begin(), prev_enabled_patches.end(), p) == prev_enabled_patches.end())
{
s_just_enabled_patches.emplace_back(p);
}
}
}
u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable_list)
u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable_list, const EnablePatchList& enable_immediately_list)
{
ActivePatchList patches_to_apply_immediately;
u32 count = 0;
for (const PatchGroup& p : patches)
{
@@ -636,6 +657,7 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
Console.WriteLn(Color_Green, fmt::format("Enabled patch: {}",
p.name.empty() ? std::string_view("<unknown>") : std::string_view(p.name)));
const bool apply_immediately = std::find(enable_immediately_list.begin(), enable_immediately_list.end(), p.name) != enable_immediately_list.end();
for (const PatchCommand& ip : p.patches)
{
// print the actual patch lines only in verbose mode (even in devel)
@@ -643,6 +665,8 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
DevCon.WriteLnFmt(" {}", ip.ToString());
s_active_patches.push_back(&ip);
if (apply_immediately && ip.placetopatch == PPT_ONCE_ON_LOAD)
patches_to_apply_immediately.push_back(&ip);
}
for (const DynamicPatch& dp : p.dpatches)
@@ -659,6 +683,16 @@ u32 Patch::EnablePatches(const PatchList& patches, const EnablePatchList& enable
count += p.name.empty() ? (static_cast<u32>(p.patches.size()) + static_cast<u32>(p.dpatches.size())) : 1;
}
if (!patches_to_apply_immediately.empty())
{
Host::RunOnCPUThread([patches = std::move(patches_to_apply_immediately)]() {
for (const PatchCommand* i : patches)
{
ApplyPatch(i);
}
});
}
return count;
}
@@ -703,10 +737,10 @@ void Patch::ReloadPatches(const std::string& serial, u32 crc, bool reload_files,
});
}
UpdateActivePatches(reload_enabled_list, verbose, verbose_if_changed);
UpdateActivePatches(reload_enabled_list, verbose, verbose_if_changed, false);
}
void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed)
void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed, bool apply_new_patches)
{
if (reload_enabled_list)
ReloadEnabledLists();
@@ -721,19 +755,19 @@ void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool ver
u32 gp_count = 0;
if (EmuConfig.EnablePatches)
{
gp_count = EnablePatches(s_gamedb_patches, EnablePatchList());
gp_count = EnablePatches(s_gamedb_patches, EnablePatchList(), EnablePatchList());
if (gp_count > 0)
message.append(TRANSLATE_PLURAL_STR("Patch", "%n GameDB patches are active.", "OSD Message", gp_count));
}
const u32 p_count = EnablePatches(s_game_patches, s_enabled_patches);
const u32 p_count = EnablePatches(s_game_patches, s_enabled_patches, apply_new_patches ? s_just_enabled_patches : EnablePatchList());
if (p_count > 0)
{
message.append_format("{}{}", message.empty() ? "" : "\n",
TRANSLATE_PLURAL_STR("Patch", "%n game patches are active.", "OSD Message", p_count));
}
const u32 c_count = EmuConfig.EnableCheats ? EnablePatches(s_cheat_patches, s_enabled_cheats) : 0;
const u32 c_count = EmuConfig.EnableCheats ? EnablePatches(s_cheat_patches, s_enabled_cheats, apply_new_patches ? s_just_enabled_cheats : EnablePatchList()) : 0;
if (c_count > 0)
{
message.append_format("{}{}", message.empty() ? "" : "\n",

View File

@@ -88,7 +88,7 @@ namespace Patch
/// Reloads cheats/patches. If verbose is set, the number of patches loaded will be shown in the OSD.
extern void ReloadPatches(const std::string& serial, u32 crc, bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed);
extern void UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed);
extern void UpdateActivePatches(bool reload_enabled_list, bool verbose, bool verbose_if_changed, bool apply_new_patches);
extern void ApplyPatchSettingOverrides();
extern bool ReloadPatchAffectingOptions();
extern void UnloadPatches();

View File

@@ -760,7 +760,7 @@ bool VMManager::ReloadGameSettings()
return false;
// Patches must come first, because they can affect aspect ratio/interlacing.
Patch::UpdateActivePatches(true, false, true);
Patch::UpdateActivePatches(true, false, true, HasValidVM());
ApplySettings();
return true;
}
@@ -2771,6 +2771,7 @@ void VMManager::Internal::EntryPointCompilingOnCPUThread()
HandleELFChange(true);
Patch::ApplyLoadedPatches(Patch::PPT_ONCE_ON_LOAD);
Patch::ApplyLoadedPatches(Patch::PPT_COMBINED_0_1);
// If the config changes at this point, it's a reset, so the game doesn't currently know about the memcard
// so there's no need to leave the eject running.
FileMcd_CancelEject();
@@ -2898,7 +2899,7 @@ void VMManager::CheckForPatchConfigChanges(const Pcsx2Config& old_config)
return;
}
Patch::UpdateActivePatches(true, false, true);
Patch::UpdateActivePatches(true, false, true, HasValidVM());
// This is a bit messy, because the patch config update happens after the settings are loaded,
// if we disable widescreen patches, we have to reload the original settings again.