diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index 6347dde5dc..615cac02b8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -160,9 +160,10 @@ extern lv2_fs_mount_point g_mp_sys_dev_hdd1; struct lv2_fs_object { - static const u32 id_base = 3; - static const u32 id_step = 1; - static const u32 id_count = 255 - id_base; + static constexpr u32 id_base = 3; + static constexpr u32 id_step = 1; + static constexpr u32 id_count = 255 - id_base; + static constexpr bool id_lowest = true; SAVESTATE_INIT_POS(40); // File Name (max 1055) diff --git a/rpcs3/Emu/IdManager.cpp b/rpcs3/Emu/IdManager.cpp index 5c09ae831d..1139866f34 100644 --- a/rpcs3/Emu/IdManager.cpp +++ b/rpcs3/Emu/IdManager.cpp @@ -29,7 +29,7 @@ std::vector>& id_manager::get_typeinfo_map return s_map; } -idm::map_data* idm::allocate_id(std::vector& vec, u32 type_id, u32 dst_id, u32 base, u32 step, u32 count, std::pair invl_range) +idm::map_data* idm::allocate_id(std::vector& vec, u32 type_id, u32 dst_id, u32 base, u32 step, u32 count, bool uses_lowest_id, std::pair invl_range) { if (const u32 index = id_manager::get_index(dst_id, base, step, count, invl_range); index < count) { @@ -46,7 +46,12 @@ idm::map_data* idm::allocate_id(std::vector& vec, u32 type_id, u32 dst return &vec[index]; } - if (vec.size() < count) + if (uses_lowest_id) + { + // Disable the optimization below (hurts accuracy for known cases) + vec.resize(count); + } + else if (vec.size() < count) { // Try to emplace back const u32 _next = base + step * ::size32(vec); diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index 991a0e756f..d94b659d02 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -35,6 +35,18 @@ namespace id_manager return T::id_invl_range; } + template + consteval bool get_force_lowest_id() + { + return false; + } + + template requires requires () { bool{T::id_lowest}; } + consteval bool get_force_lowest_id() + { + return T::id_lowest; + } + template concept IdmCompatible = requires () { T::id_base, T::id_step, T::id_count; }; @@ -56,6 +68,7 @@ namespace id_manager }; static constexpr std::pair invl_range = get_invl_range(); + static constexpr bool uses_lowest_id = get_force_lowest_id(); static_assert(count && step && u64{step} * (count - 1) + base < u32{umax} + u64{base != 0 ? 1 : 0}, "ID traits: invalid object range"); @@ -130,6 +143,7 @@ namespace id_manager u32 base; u32 step; u32 count; + bool uses_lowest_id; std::pair invl_range; // Get type index @@ -168,7 +182,7 @@ namespace id_manager +id_traits_load_func::load, +[](utils::serial& ar, void* obj) { static_cast(obj)->save(ar); }, +id_traits_savable_func::savable, - id_traits::base, id_traits::step, id_traits::count, id_traits::invl_range, + id_traits::base, id_traits::step, id_traits::count, id_traits::uses_lowest_id, id_traits::invl_range, }; const u128 key = u128{get_type()} << 64 | std::bit_cast(C::savestate_init_pos); @@ -192,7 +206,7 @@ namespace id_manager nullptr, nullptr, nullptr, - id_traits::base, id_traits::step, id_traits::count, id_traits::invl_range, + id_traits::base, id_traits::step, id_traits::count, id_traits::uses_lowest_id, id_traits::invl_range, }; } @@ -426,7 +440,7 @@ class idm using map_data = std::pair>; // Prepare new ID (returns nullptr if out of resources) - static map_data* allocate_id(std::vector& vec, u32 type_id, u32 dst_id, u32 base, u32 step, u32 count, std::pair invl_range); + static map_data* allocate_id(std::vector& vec, u32 type_id, u32 dst_id, u32 base, u32 step, u32 count, bool uses_lowest_id, std::pair invl_range); // Get object by internal index if exists (additionally check type if types are not equal) template @@ -485,7 +499,7 @@ class idm auto& map = g_fxo->get>(); - if (auto* place = allocate_id(map.vec, get_type(), id, traits::base, traits::step, traits::count, traits::invl_range)) + if (auto* place = allocate_id(map.vec, get_type(), id, traits::base, traits::step, traits::count, traits::uses_lowest_id, traits::invl_range)) { // Get object, store it place->second = provider();