mirror of
https://github.com/RPCS3/rpcs3
synced 2024-07-01 07:04:22 +00:00
Compare commits
7 Commits
dc624471e7
...
90a5f8410b
Author | SHA1 | Date | |
---|---|---|---|
|
90a5f8410b | ||
|
71524271e9 | ||
|
d5923ef808 | ||
|
ef136acb6c | ||
|
a5956cfa82 | ||
|
703de01ebf | ||
|
660a37c7a0 |
|
@ -2112,6 +2112,138 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b
|
|||
}
|
||||
|
||||
ppu_log.notice("Block analysis: %zu blocks (%zu enqueued)", funcs.size(), block_queue.size());
|
||||
|
||||
std::unordered_map<std::string_view, std::pair<u32, u32>> duplicate_data_map;
|
||||
duplicate_map.clear();
|
||||
|
||||
for (auto& func : funcs)
|
||||
{
|
||||
if (func.size == 0 || func.size > 10000u)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& data = duplicate_data_map[std::string_view{get_ptr<char>(func.addr), func.size}];
|
||||
|
||||
const usz count = data.first;
|
||||
|
||||
if (!count)
|
||||
{
|
||||
data.first++;
|
||||
data.second = func.addr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!data.second)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
const u32 faddr = func.addr;
|
||||
const u32 fend = func.addr + func.size;
|
||||
|
||||
bool fail = false;
|
||||
|
||||
//for (const auto [addr, size] : func.blocks)
|
||||
const u32 addr = func.addr;
|
||||
const u32 size = func.size;
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto i_ptr = ensure(get_ptr<u32>(addr));
|
||||
|
||||
for (u32 i = addr; i < fend; i += 4, i_ptr++)
|
||||
{
|
||||
/ const ppu_opcode_t op{*i_ptr};
|
||||
const auto itype = s_ppu_itype.decode(op.opcode);
|
||||
|
||||
if (itype != ppu_itype::BC && itype != ppu_itype::B)
|
||||
{
|
||||
if (i == fend - 4)
|
||||
{
|
||||
if (!(itype & ppu_itype::branch))
|
||||
{
|
||||
// Inserts a branch to following code
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!op.aa)
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (itype == ppu_itype::BC && (op.bo & 0x14) != 0x14)
|
||||
{
|
||||
if (i == fend - 4)
|
||||
{
|
||||
// Can branch to next
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fail)
|
||||
{
|
||||
data.first = 1;
|
||||
data.second = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
data.first++;
|
||||
|
||||
// Choose the lowest function as the source
|
||||
data.second = std::min<u32>(data.second, func.addr);
|
||||
}
|
||||
|
||||
usz dups_count = 0;
|
||||
|
||||
for (auto& func : funcs)
|
||||
{
|
||||
if (func.size == 0 || func.size > 10000u)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto data = ::at32(duplicate_data_map, std::string_view{get_ptr<char>(func.addr), func.size});
|
||||
|
||||
if (data.first > 1)
|
||||
{
|
||||
duplicate_map[func.addr] = data.second;
|
||||
|
||||
for (const auto [addr, size] : func.blocks)
|
||||
{
|
||||
if (size == 0 || addr >= func.addr + func.size)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
duplicate_map[addr] = data.second + (addr - func.addr);
|
||||
}
|
||||
|
||||
if (func.addr != data.second)
|
||||
{
|
||||
dups_count++;
|
||||
}
|
||||
|
||||
ppu_log.trace("Found PPU function duplicate: func 0x%x vs 0x%x (%d times) (size=%d)", func.addr, data.second, data.first, func.size);
|
||||
}
|
||||
}
|
||||
|
||||
ppu_log.success("Function duplication count: %d/%d (%g%)", dups_count, duplicate_data_map.size(), dups_count * 100.0 / duplicate_data_map.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ struct ppu_module
|
|||
std::vector<ppu_function> funcs{};
|
||||
std::deque<std::shared_ptr<void>> allocations;
|
||||
std::map<u32, u32> addr_to_seg_index;
|
||||
std::unordered_map<u32, u32> duplicate_map;
|
||||
|
||||
// Copy info without functions
|
||||
void copy_part(const ppu_module& info)
|
||||
|
@ -107,6 +108,7 @@ struct ppu_module
|
|||
secs = info.secs;
|
||||
allocations = info.allocations;
|
||||
addr_to_seg_index = info.addr_to_seg_index;
|
||||
duplicate_map = info.duplicate_map;
|
||||
}
|
||||
|
||||
bool analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string<u32>& applied, const std::vector<u32>& exported_funcs = std::vector<u32>{}, std::function<bool()> check_aborted = {});
|
||||
|
|
|
@ -3923,13 +3923,13 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
|||
mself_header hdr{};
|
||||
|
||||
if (mself.read(hdr) && hdr.get_count(mself.size()))
|
||||
{
|
||||
{
|
||||
std::set<u64> offs;
|
||||
|
||||
for (u32 j = 0; j < hdr.count; j++)
|
||||
{
|
||||
mself_record rec{};
|
||||
|
||||
std::set<u64> offs;
|
||||
|
||||
if (mself.read(rec) && rec.get_pos(mself.size()))
|
||||
{
|
||||
if (rec.size <= 0x20)
|
||||
|
@ -4170,7 +4170,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
|||
}
|
||||
|
||||
ppu_log.notice("Failed to precompile '%s' (prx: %s, ovl: %s): Attempting compilation as executable file", path, prx_err, ovl_err);
|
||||
possible_exec_file_paths.push(path, offset, file_size);
|
||||
possible_exec_file_paths.push(file_queue[func_i]);
|
||||
inc_fdone = 0;
|
||||
}
|
||||
|
||||
|
@ -4676,8 +4676,15 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
|||
// Copy block or function entry
|
||||
ppu_function& entry = part.funcs.emplace_back(func);
|
||||
|
||||
u32 og_func = entry.addr;
|
||||
|
||||
if (auto it = info.duplicate_map.find(entry.addr); it != info.duplicate_map.end())
|
||||
{
|
||||
og_func = it->second;
|
||||
}
|
||||
|
||||
// Fixup some information
|
||||
entry.name = fmt::format("__0x%x", entry.addr - reloc);
|
||||
entry.name = fmt::format("__0x%x", og_func - reloc);
|
||||
|
||||
if (has_mfvscr && g_cfg.core.ppu_set_sat_bit)
|
||||
{
|
||||
|
@ -4844,7 +4851,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
|||
settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose
|
||||
|
||||
// Write version, hash, CPU, settings
|
||||
fmt::append(obj_name, "v6-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||
fmt::append(obj_name, "v7-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||
}
|
||||
|
||||
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
||||
|
@ -5098,6 +5105,9 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
|||
jit_mod.symbol_resolver(vm::g_exec_addr, info.segs[0].addr);
|
||||
|
||||
// Find a BLR-only function in order to copy it to all BLRs (some games need it)
|
||||
bool early_exit = false;
|
||||
|
||||
// Get and install function addresses
|
||||
for (const auto& func : info.funcs)
|
||||
{
|
||||
if (func.size == 4 && *info.get_ptr<u32>(func.addr) == ppu_instructions::BLR())
|
||||
|
@ -5168,6 +5178,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
|||
{
|
||||
if (func.size)
|
||||
{
|
||||
if (auto it = module_part.duplicate_map.find(func.addr); it != module_part.duplicate_map.end() && it->second != it->first)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto f = cast<Function>(_module->getOrInsertFunction(func.name, _func).getCallee());
|
||||
f->setCallingConv(CallingConv::GHC);
|
||||
f->addParamAttr(1, llvm::Attribute::NoAlias);
|
||||
|
@ -5241,6 +5256,15 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
|||
|
||||
if (module_part.funcs[fi].size)
|
||||
{
|
||||
const u32 faddr = module_part.funcs[fi].addr;
|
||||
auto it = module_part.duplicate_map.find(faddr);
|
||||
|
||||
if (it != module_part.duplicate_map.end() && it->second != faddr)
|
||||
{
|
||||
ppu_log.trace("LLVM: Function 0x%x was skipped (duplicate)", faddr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Translate
|
||||
if (const auto func = translator.Translate(module_part.funcs[fi]))
|
||||
{
|
||||
|
|
|
@ -315,6 +315,9 @@ usb_device_rb3_midi_drums::Definition::Definition(std::string name, const std::s
|
|||
usb_device_rb3_midi_drums::usb_device_rb3_midi_drums(const std::array<u8, 7>& location, const std::string& device_name)
|
||||
: usb_device_emulated(location)
|
||||
{
|
||||
m_id_to_note_mapping = midi::create_id_to_note_mapping();
|
||||
combo.reload_definitions();
|
||||
|
||||
UsbDeviceDescriptor descriptor{};
|
||||
descriptor.bcdDevice = 0x0200;
|
||||
descriptor.bDeviceClass = 0x00;
|
||||
|
|
|
@ -1549,4 +1549,26 @@ namespace rsx
|
|||
{
|
||||
return get_format_block_size_in_bytes(format) == 2 ? 0xFFFF : 0xFFFFFF;
|
||||
}
|
||||
|
||||
bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
// Clamping modes
|
||||
default:
|
||||
rsx_log.error("Unknown texture wrap mode: %d", static_cast<int>(mode));
|
||||
[[ fallthrough ]];
|
||||
case rsx::texture_wrap_mode::border:
|
||||
case rsx::texture_wrap_mode::clamp:
|
||||
case rsx::texture_wrap_mode::clamp_to_edge:
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp_to_edge:
|
||||
case rsx::texture_wrap_mode::mirror_once_border:
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp:
|
||||
return false;
|
||||
// Wrapping modes
|
||||
case rsx::texture_wrap_mode::wrap:
|
||||
case rsx::texture_wrap_mode::mirror:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,4 +286,6 @@ namespace rsx
|
|||
|
||||
format_class classify_format(rsx::surface_depth_format2 format);
|
||||
format_class classify_format(u32 gcm_format);
|
||||
|
||||
bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode);
|
||||
}
|
||||
|
|
|
@ -332,6 +332,9 @@ namespace glsl
|
|||
{ "SEXT_G_BIT" , rsx::texture_control_bits::SEXT_G },
|
||||
{ "SEXT_B_BIT" , rsx::texture_control_bits::SEXT_B },
|
||||
{ "SEXT_A_BIT" , rsx::texture_control_bits::SEXT_A },
|
||||
{ "WRAP_S_BIT", rsx::texture_control_bits::WRAP_S },
|
||||
{ "WRAP_T_BIT", rsx::texture_control_bits::WRAP_T },
|
||||
{ "WRAP_R_BIT", rsx::texture_control_bits::WRAP_R },
|
||||
|
||||
{ "ALPHAKILL ", rsx::texture_control_bits::ALPHAKILL },
|
||||
{ "RENORMALIZE ", rsx::texture_control_bits::RENORMALIZE },
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace rsx
|
|||
FILTERED_MIN,
|
||||
UNNORMALIZED_COORDS,
|
||||
CLAMP_TEXCOORDS_BIT,
|
||||
WRAP_S,
|
||||
WRAP_T,
|
||||
WRAP_R,
|
||||
|
||||
GAMMA_CTRL_MASK = (1 << GAMMA_R) | (1 << GAMMA_G) | (1 << GAMMA_B) | (1 << GAMMA_A),
|
||||
EXPAND_MASK = (1 << EXPAND_R) | (1 << EXPAND_G) | (1 << EXPAND_B) | (1 << EXPAND_A),
|
||||
|
|
|
@ -27,4 +27,16 @@ vec3 compute2x2DownsampleWeights(const in float coord, const in float uv_step, c
|
|||
return vec3(1.0 - (computed_weights.x + computed_weights.y), computed_weights.xy);
|
||||
}
|
||||
|
||||
vec2 texture2DMSCoord(const in vec2 coords, const in uint flags)
|
||||
{
|
||||
if (0u == (flags & (WRAP_S_MASK | WRAP_T_MASK)))
|
||||
{
|
||||
return coords;
|
||||
}
|
||||
|
||||
const vec2 wrapped_coords = mod(coords, vec2(1.0));
|
||||
const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK));
|
||||
return _select(coords, wrapped_coords, wrap_control_mask);
|
||||
}
|
||||
|
||||
)"
|
||||
|
|
|
@ -12,7 +12,7 @@ vec4 sampleTexture2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 coords, const i
|
|||
{
|
||||
const uint flags = TEX_FLAGS(index);
|
||||
const vec2 scaled_coords = COORD_SCALE2(index, coords);
|
||||
const vec2 normalized_coords = mod(scaled_coords, vec2(1.0));
|
||||
const vec2 normalized_coords = texture2DMSCoord(scaled_coords, flags);
|
||||
const vec2 sample_count = vec2(2., textureSamples(tex) * 0.5);
|
||||
const vec2 image_size = textureSize(tex) * sample_count;
|
||||
const ivec2 icoords = ivec2(normalized_coords * image_size);
|
||||
|
|
|
@ -11,6 +11,9 @@ R"(
|
|||
#define SEXT_G_MASK (1 << SEXT_G_BIT)
|
||||
#define SEXT_B_MASK (1 << SEXT_B_BIT)
|
||||
#define SEXT_A_MASK (1 << SEXT_A_BIT)
|
||||
#define WRAP_S_MASK (1 << WRAP_S_BIT)
|
||||
#define WRAP_T_MASK (1 << WRAP_T_BIT)
|
||||
#define WRAP_R_MASK (1 << WRAP_R_BIT)
|
||||
|
||||
#define GAMMA_CTRL_MASK (GAMMA_R_MASK | GAMMA_G_MASK | GAMMA_B_MASK | GAMMA_A_MASK)
|
||||
#define SIGN_EXPAND_MASK (EXPAND_R_MASK | EXPAND_G_MASK | EXPAND_B_MASK | EXPAND_A_MASK)
|
||||
|
|
|
@ -2525,14 +2525,28 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
if (backend_config.supports_hw_msaa &&
|
||||
sampler_descriptors[i]->samples > 1)
|
||||
if (backend_config.supports_hw_msaa && sampler_descriptors[i]->samples > 1)
|
||||
{
|
||||
current_fp_texture_state.multisampled_textures |= (1 << i);
|
||||
texture_control |= (static_cast<u32>(tex.zfunc()) << texture_control_bits::DEPTH_COMPARE_OP);
|
||||
texture_control |= (static_cast<u32>(tex.mag_filter() != rsx::texture_magnify_filter::nearest) << texture_control_bits::FILTERED_MAG);
|
||||
texture_control |= (static_cast<u32>(tex.min_filter() != rsx::texture_minify_filter::nearest) << texture_control_bits::FILTERED_MIN);
|
||||
texture_control |= (((tex.format() & CELL_GCM_TEXTURE_UN) >> 6) << texture_control_bits::UNNORMALIZED_COORDS);
|
||||
|
||||
if (rsx::is_texcoord_wrapping_mode(tex.wrap_s()))
|
||||
{
|
||||
texture_control |= (1 << texture_control_bits::WRAP_S);
|
||||
}
|
||||
|
||||
if (rsx::is_texcoord_wrapping_mode(tex.wrap_t()))
|
||||
{
|
||||
texture_control |= (1 << texture_control_bits::WRAP_T);
|
||||
}
|
||||
|
||||
if (rsx::is_texcoord_wrapping_mode(tex.wrap_r()))
|
||||
{
|
||||
texture_control |= (1 << texture_control_bits::WRAP_R);
|
||||
}
|
||||
}
|
||||
|
||||
if (sampler_descriptors[i]->format_class != RSX_FORMAT_CLASS_COLOR)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
LOG_CHANNEL(ds3_log, "DS3");
|
||||
|
||||
using namespace reports;
|
||||
|
||||
constexpr std::array<u8, 6> battery_capacity = {0, 1, 25, 50, 75, 100};
|
||||
|
||||
constexpr id_pair SONY_DS3_ID_0 = {0x054C, 0x0268};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
namespace reports
|
||||
{
|
||||
struct ds3_rumble
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
#ifdef _WIN32
|
||||
u8 report_id = 0;
|
||||
#endif
|
||||
ds3_input_report report{};
|
||||
reports::ds3_input_report report{};
|
||||
};
|
||||
|
||||
class ds3_pad_handler final : public hid_pad_handler<ds3_device>
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
LOG_CHANNEL(ds4_log, "DS4");
|
||||
|
||||
using namespace reports;
|
||||
|
||||
constexpr id_pair SONY_DS4_ID_0 = {0x054C, 0x0BA0}; // Dongle
|
||||
constexpr id_pair SONY_DS4_ID_1 = {0x054C, 0x05C4}; // CUH-ZCT1x
|
||||
constexpr id_pair SONY_DS4_ID_2 = {0x054C, 0x09CC}; // CUH-ZCT2x
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
namespace reports
|
||||
{
|
||||
constexpr u32 DS4_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DS4_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
|
@ -119,8 +119,8 @@ public:
|
|||
bool bt_controller{false};
|
||||
bool has_calib_data{false};
|
||||
std::array<CalibData, CalibIndex::COUNT> calib_data{};
|
||||
ds4_input_report_usb report_usb{};
|
||||
ds4_input_report_bt report_bt{};
|
||||
reports::ds4_input_report_usb report_usb{};
|
||||
reports::ds4_input_report_bt report_bt{};
|
||||
};
|
||||
|
||||
class ds4_pad_handler final : public hid_pad_handler<DS4Device>
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
LOG_CHANNEL(dualsense_log, "DualSense");
|
||||
|
||||
using namespace reports;
|
||||
|
||||
template <>
|
||||
void fmt_class_string<DualSenseDevice::DualSenseDataMode>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
namespace reports
|
||||
{
|
||||
constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
|
@ -172,7 +172,7 @@ public:
|
|||
u8 bt_sequence{0};
|
||||
bool has_calib_data{false};
|
||||
std::array<CalibData, CalibIndex::COUNT> calib_data{};
|
||||
dualsense_input_report_common report{}; // No need to have separate reports for usb and bluetooth
|
||||
reports::dualsense_input_report_common report{}; // No need to have separate reports for usb and bluetooth
|
||||
DualSenseDataMode data_mode{DualSenseDataMode::Simple};
|
||||
DualSenseFeatureSet feature_set{DualSenseFeatureSet::Normal};
|
||||
bool init_lightbar{true};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
LOG_CHANNEL(skateboard_log, "Skateboard");
|
||||
|
||||
using namespace reports;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr id_pair SKATEBOARD_ID_0 = {0x12BA, 0x0400}; // Tony Hawk RIDE Skateboard
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
namespace reports
|
||||
{
|
||||
// Descriptor
|
||||
// 0x09, 0x05, // Usage (0x05)
|
||||
|
@ -143,7 +143,7 @@ class skateboard_device : public HidDevice
|
|||
{
|
||||
public:
|
||||
bool skateboard_is_on = false;
|
||||
skateboard_input_report report{};
|
||||
reports::skateboard_input_report report{};
|
||||
};
|
||||
|
||||
class skateboard_pad_handler final : public hid_pad_handler<skateboard_device>
|
||||
|
|
Loading…
Reference in New Issue
Block a user