mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
PPU: Add new patch function for SONIC 06
This commit is contained in:
parent
681a6ef73c
commit
f572e29a13
@ -718,7 +718,7 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
// Always executable
|
||||
u64 flags = vm::alloc_executable | vm::alloc_unwritable;
|
||||
|
||||
switch (p.offset % patch_engine::mem_protection::mask)
|
||||
switch (p.offset & patch_engine::mem_protection::mask)
|
||||
{
|
||||
case patch_engine::mem_protection::rw:
|
||||
case patch_engine::mem_protection::wx:
|
||||
@ -754,15 +754,26 @@ static usz apply_modification(std::basic_string<u32>& applied, const patch_engin
|
||||
// Register code
|
||||
ppu_register_range(addr, alloc_size);
|
||||
|
||||
// Write branch to code
|
||||
ppu_form_branch_to_code(out_branch, addr);
|
||||
resval = out_branch & -4;
|
||||
|
||||
// Write branch to return to code
|
||||
if (!ppu_form_branch_to_code(addr + static_cast<u32>(p.value.long_value) * 4, resval + 4))
|
||||
{
|
||||
patch_log.error("Failed to write return jump at 0x%x", addr + static_cast<u32>(p.value.long_value) * 4);
|
||||
ensure(alloc_map->dealloc(addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Write branch to code
|
||||
if (!ppu_form_branch_to_code(out_branch, addr))
|
||||
{
|
||||
patch_log.error("Failed to jump to code cave at 0x%x", out_branch);
|
||||
ensure(alloc_map->dealloc(addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Write address of the allocated memory to the code entry
|
||||
*vm::get_super_ptr<u32>(resval) = addr;
|
||||
|
||||
// Write branch to return to code
|
||||
ppu_form_branch_to_code(addr + static_cast<u32>(p.value.long_value) * 4, resval + 4);
|
||||
relocate_instructions_at = addr;
|
||||
break;
|
||||
}
|
||||
|
@ -322,6 +322,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||
Cell/Modules/cellVoice.cpp
|
||||
Cell/Modules/cellVpost.cpp
|
||||
Cell/Modules/cellWebBrowser.cpp
|
||||
Cell/Modules/HLE_PATCHES.cpp
|
||||
Cell/Modules/libad_async.cpp
|
||||
Cell/Modules/libad_core.cpp
|
||||
Cell/Modules/libmedi.cpp
|
||||
|
58
rpcs3/Emu/Cell/Modules/HLE_PATCHES.cpp
Normal file
58
rpcs3/Emu/Cell/Modules/HLE_PATCHES.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Utilities/Thread.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "Emu/Cell/lv2/sys_sync.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
// SONIC THE HEDGEDOG: a fix for a race condition between SPUs and PPUs causing missing graphics (SNR is overriden when non-empty)
|
||||
void WaitForSPUsToEmptySNRs(ppu_thread& ppu, u32 spu_id, u32 snr_mask)
|
||||
{
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
auto [spu, group] = lv2_spu_group::get_thread(spu_id);
|
||||
|
||||
if ((!spu && spu_id != umax) || snr_mask % 4 == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait until specified SNRs are reported empty at least once
|
||||
for (bool has_busy = true; has_busy && !ppu.is_stopped(); std::this_thread::yield())
|
||||
{
|
||||
has_busy = false;
|
||||
|
||||
auto for_one = [&](u32, spu_thread& spu)
|
||||
{
|
||||
if ((snr_mask & 1) && spu.ch_snr1.get_count())
|
||||
{
|
||||
has_busy = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((snr_mask & 2) && spu.ch_snr2.get_count())
|
||||
{
|
||||
has_busy = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (spu)
|
||||
{
|
||||
// Wait for a single SPU
|
||||
for_one(spu->id, *spu);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait for all SPUs
|
||||
idm::select<named_thread<spu_thread>>(for_one);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE(ppu_module_manager::hle_patches)("RPCS3_HLE_LIBRARY", []()
|
||||
{
|
||||
REG_FUNC(RPCS3_HLE_LIBRARY, WaitForSPUsToEmptySNRs);
|
||||
});
|
@ -163,7 +163,7 @@ bool statichle_handler::check_against_patterns(vm::cptr<u8>& data, u32 size, u32
|
||||
}
|
||||
|
||||
const auto sfunc = &::at32(smodule->functions, pat.fnid);
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(sfunc->index) + 4;
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(sfunc->index, true);
|
||||
|
||||
// write stub
|
||||
vm::write32(addr, ppu_instructions::LIS(0, (target&0xFFFF0000)>>16));
|
||||
|
@ -290,14 +290,14 @@ public:
|
||||
return access(llvm);
|
||||
}
|
||||
|
||||
u32 func_addr(u32 index) const
|
||||
u32 func_addr(u32 index, bool is_code_addr = false) const
|
||||
{
|
||||
if (index >= access().size() || !addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addr + index * 8;
|
||||
return addr + index * 8 + (is_code_addr ? 4 : 0);
|
||||
}
|
||||
|
||||
// Allocation address
|
||||
|
@ -153,7 +153,7 @@ struct ppu_linkage_info
|
||||
|
||||
// Module map
|
||||
std::map<std::string, module_data> modules{};
|
||||
std::map<std::string, std::shared_ptr<atomic_t<bool>>, std::less<>> lib_lock;
|
||||
std::map<std::string, atomic_t<bool>, std::less<>> lib_lock;
|
||||
shared_mutex mutex;
|
||||
};
|
||||
|
||||
@ -278,6 +278,7 @@ static void ppu_initialize_modules(ppu_linkage_info* link, utils::serial* ar = n
|
||||
&ppu_module_manager::sys_libc,
|
||||
&ppu_module_manager::sys_lv2dbg,
|
||||
&ppu_module_manager::static_hle,
|
||||
&ppu_module_manager::hle_patches,
|
||||
};
|
||||
|
||||
// Initialize double-purpose fake OPD array for HLE functions
|
||||
@ -640,9 +641,9 @@ extern bool ppu_register_library_lock(std::string_view libname, bool lock_lib)
|
||||
|
||||
reader_lock lock(link->mutex);
|
||||
|
||||
if (auto it = std::as_const(link->lib_lock).find(libname); it != link->lib_lock.cend() && it->second)
|
||||
if (auto it = link->lib_lock.find(libname); it != link->lib_lock.cend())
|
||||
{
|
||||
return lock_lib ? !it->second->test_and_set() : it->second->test_and_reset();
|
||||
return lock_lib ? !it->second.test_and_set() : it->second.test_and_reset();
|
||||
}
|
||||
|
||||
if (!lock_lib)
|
||||
@ -653,15 +654,9 @@ extern bool ppu_register_library_lock(std::string_view libname, bool lock_lib)
|
||||
|
||||
lock.upgrade();
|
||||
|
||||
auto& lib_lock = link->lib_lock.emplace(std::string{libname}, nullptr).first->second;
|
||||
auto& lib_lock = link->lib_lock.emplace(std::string{libname}, false).first->second;
|
||||
|
||||
if (!lib_lock)
|
||||
{
|
||||
lib_lock = std::make_shared<atomic_t<bool>>(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return !lib_lock->test_and_set();
|
||||
return !lib_lock.test_and_set();
|
||||
}
|
||||
|
||||
// Load and register exports; return special exports found (nameless module)
|
||||
@ -750,7 +745,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo
|
||||
if (_sf && (_sf->flags & MFF_FORCED_HLE))
|
||||
{
|
||||
// Inject a branch to the HLE implementation
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(_sf->index) + 4;
|
||||
const u32 target = g_fxo->get<ppu_function_manager>().func_addr(_sf->index, true);
|
||||
|
||||
// Set exported function
|
||||
flink.export_addr = target - 4;
|
||||
|
@ -80,9 +80,9 @@ public:
|
||||
std::unordered_map<u32, ppu_static_function, value_hash<u32>> functions{};
|
||||
std::unordered_map<u32, ppu_static_variable, value_hash<u32>> variables{};
|
||||
|
||||
public:
|
||||
ppu_static_module(const char* name);
|
||||
|
||||
public:
|
||||
ppu_static_module(const char* name, void(*init)())
|
||||
: ppu_static_module(name)
|
||||
{
|
||||
@ -278,6 +278,7 @@ public:
|
||||
static const ppu_static_module sys_libc;
|
||||
static const ppu_static_module sys_lv2dbg;
|
||||
static const ppu_static_module static_hle;
|
||||
static const ppu_static_module hle_patches;
|
||||
|
||||
private:
|
||||
inline static std::unordered_map<std::string, ppu_static_module*> s_module_map;
|
||||
|
@ -667,7 +667,7 @@ struct ppu_far_jumps_t
|
||||
// NOTE: In order to clean up this information all calls must return in order
|
||||
auto& saved_info = calls_info.emplace_back();
|
||||
saved_info.cia = pc;
|
||||
saved_info.saved_lr = std::exchange(ppu->lr, FIND_FUNC(ppu_return_from_far_jump));
|
||||
saved_info.saved_lr = std::exchange(ppu->lr, g_fxo->get<ppu_function_manager>().func_addr(FIND_FUNC(ppu_return_from_far_jump), true));
|
||||
saved_info.saved_r2 = std::exchange(ppu->gpr[2], opd.rtoc);
|
||||
}
|
||||
|
||||
@ -1243,7 +1243,7 @@ std::vector<std::pair<u32, u32>> ppu_thread::dump_callstack_list() const
|
||||
}
|
||||
|
||||
// Ignore HLE stop address
|
||||
return addr == g_fxo->get<ppu_function_manager>().func_addr(1) + 4;
|
||||
return addr == g_fxo->get<ppu_function_manager>().func_addr(1, true);
|
||||
};
|
||||
|
||||
if (is_invalid(addr))
|
||||
@ -1921,7 +1921,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc)
|
||||
interrupt_thread_executing = true;
|
||||
cia = addr;
|
||||
gpr[2] = rtoc;
|
||||
lr = g_fxo->get<ppu_function_manager>().func_addr(1) + 4; // HLE stop address
|
||||
lr = g_fxo->get<ppu_function_manager>().func_addr(1, true); // HLE stop address
|
||||
current_function = nullptr;
|
||||
|
||||
if (std::exchange(loaded_from_savestate, false))
|
||||
|
@ -66,6 +66,7 @@
|
||||
<ClCompile Include="Emu\Cell\Modules\cellMusicSelectionContext.cpp" />
|
||||
<ClCompile Include="Emu\Cell\Modules\libfs_utility_init.cpp" />
|
||||
<ClCompile Include="Emu\Cell\Modules\sys_crashdump.cpp" />
|
||||
<ClCompile Include="Emu\Cell\Modules\HLE_PATCHES.cpp" />
|
||||
<ClCompile Include="Emu\Io\camera_config.cpp" />
|
||||
<ClCompile Include="Emu\Io\recording_config.cpp" />
|
||||
<ClCompile Include="Emu\Io\Turntable.cpp" />
|
||||
|
@ -1101,6 +1101,8 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\Io\recording_config.cpp">
|
||||
<Filter>Emu\Io</Filter>
|
||||
<ClCompile Include="Emu\Cell\Modules\HLE_PATCHES.cpp">
|
||||
<Filter>Emu\Cell\Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user