IdManager improved

This commit is contained in:
Nekotekina 2017-01-25 20:50:30 +03:00 committed by Ivan
parent 6c189511af
commit 591a6c8671
43 changed files with 408 additions and 307 deletions

View File

@ -839,34 +839,6 @@ struct multicast<T, Value, void>
}
};
// Tagged ID type
template <typename T = void, typename ID = u32>
class id_value
{
// Initial value
mutable ID m_value{static_cast<ID>(-1)};
// Allow access for ID manager
friend class idm;
// Update ID
void operator=(const ID& value) const
{
m_value = value;
}
public:
constexpr id_value()
{
}
// Get the value
operator ID() const
{
return m_value;
}
};
// Error code type (return type), implements error reporting. Could be a template.
struct error_code
{
@ -921,14 +893,3 @@ constexpr FORCE_INLINE error_code::not_an_error not_an_error(const T& value)
{
return static_cast<error_code::not_an_error>(static_cast<s32>(value));
}
template <typename T, typename ID>
struct fmt_unveil<id_value<T, ID>>
{
using type = typename fmt_unveil<ID>::type;
static inline auto get(const id_value<T, ID>& value)
{
return fmt_unveil<ID>::get(value);
}
};

View File

@ -93,7 +93,8 @@ cpu_thread::~cpu_thread()
{
}
cpu_thread::cpu_thread()
cpu_thread::cpu_thread(u32 id)
: id(id)
{
}

View File

@ -31,9 +31,9 @@ public:
virtual void on_stop() override;
virtual ~cpu_thread() override;
const id_value<> id{};
const u32 id;
cpu_thread();
cpu_thread(u32 id);
// Public thread state
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
@ -50,6 +50,12 @@ public:
// Set cpu_flag::signal
void set_signal();
// Check thread type
u32 id_type()
{
return id >> 24;
}
// Print CPU state
virtual std::string dump() const;

View File

@ -143,10 +143,14 @@ class ElementaryStream
bool is_full(u32 space);
public:
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);
Demuxer* dmux;
const id_value<> id{};
const u32 id = idm::last_id();
const u32 memAddr;
const u32 memSize;
const u32 fidMajor;

View File

@ -109,6 +109,10 @@ struct CellJpgDecDataOutInfo
// Custom structs
struct CellJpgDecSubHandle
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
u32 fd;
u64 fileSize;
CellJpgDecInfo info;

View File

@ -321,6 +321,10 @@ struct CellVpostPictureInfo
class VpostInstance
{
public:
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const bool to_rgba;
VpostInstance(bool rgba)

View File

@ -16,7 +16,11 @@ logs::channel sceNpTrophy("sceNpTrophy", logs::level::notice);
struct trophy_context_t
{
const id_value<> id{};
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const u32 id = idm::last_id();
std::string trp_name;
fs::file trp_stream;
@ -25,7 +29,11 @@ struct trophy_context_t
struct trophy_handle_t
{
const id_value<> id{};
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const u32 id = idm::last_id();
};
// Functions

View File

@ -9,6 +9,10 @@ extern logs::channel sysPrxForUser;
struct HeapInfo
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name;
HeapInfo(const char* name)

View File

@ -11,6 +11,10 @@ using sys_mempool_t = u32;
struct memory_pool_t
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
vm::ptr<void> chunk;
u64 chunk_size;
u64 block_size;

View File

@ -86,10 +86,9 @@ int inet_pton(int af, const char *src, char *dst)
// We map host sockets to sequential IDs to return as descriptors because syscalls expect socket IDs to be under 1024.
struct sys_net_socket final
{
using id_base = sys_net_socket;
static constexpr u32 id_min = 0; // Minimal valid socket number is 0 (not 1).
static constexpr u32 id_max = 1023;
static const u32 id_base = 0;
static const u32 id_step = 1;
static const u32 id_count = 1024;
sys_net::socket_t s = -1;

View File

@ -253,7 +253,7 @@ ppu_thread::~ppu_thread()
}
ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack)
: cpu_thread()
: cpu_thread(idm::last_id())
, prio(prio)
, stack_size(std::max<u32>(stack, 0x4000))
, stack_addr(vm::alloc(stack_size, vm::stack))
@ -404,7 +404,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
u32 ppu_thread::stack_push(u32 size, u32 align_v)
{
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min)
if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
{
ppu_thread& context = static_cast<ppu_thread&>(*cpu);
@ -430,7 +430,7 @@ u32 ppu_thread::stack_push(u32 size, u32 align_v)
void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept
{
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min)
if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
{
ppu_thread& context = static_cast<ppu_thread&>(*cpu);

View File

@ -20,10 +20,9 @@ enum class ppu_cmd : u32
class ppu_thread : public cpu_thread
{
public:
using id_base = ppu_thread;
static constexpr u32 id_min = 0x70000000; // TODO (used to determine thread type)
static constexpr u32 id_max = 0x7fffffff;
static const u32 id_base = 0x01000000; // TODO (used to determine thread type)
static const u32 id_step = 1;
static const u32 id_count = 65535;
virtual std::string get_name() const override;
virtual std::string dump() const override;

View File

@ -7,12 +7,9 @@ class RawSPUThread final : public SPUThread
void cpu_task() override;
public:
/* IdManager setups */
using id_base = RawSPUThread;
static constexpr u32 id_min = 0;
static constexpr u32 id_max = 4;
static const u32 id_base = 0;
static const u32 id_step = 1;
static const u32 id_count = 5;
void on_init(const std::shared_ptr<void>&) override;

View File

@ -238,7 +238,7 @@ SPUThread::~SPUThread()
}
SPUThread::SPUThread(const std::string& name)
: cpu_thread()
: cpu_thread(idm::last_id())
, m_name(name)
, index(0)
, offset(0)
@ -246,7 +246,7 @@ SPUThread::SPUThread(const std::string& name)
}
SPUThread::SPUThread(const std::string& name, u32 index)
: cpu_thread()
: cpu_thread(idm::last_id())
, m_name(name)
, index(index)
, offset(verify("SPU LS" HERE, vm::alloc(0x40000, vm::main)))

View File

@ -501,6 +501,10 @@ protected:
SPUThread(const std::string& name);
public:
static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
static const u32 id_step = 1;
static const u32 id_count = 65535;
SPUThread(const std::string& name, u32 index);
std::array<v128, 128> gpr; // General-Purpose Registers

View File

@ -19,6 +19,10 @@ struct sys_cond_attribute_t
struct lv2_cond_t
{
static const u32 id_base = 0x86000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name;
const std::shared_ptr<lv2_mutex_t> mutex; // associated mutex

View File

@ -18,20 +18,25 @@ extern u64 get_system_time();
std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
{
auto queue = std::make_shared<lv2_event_queue_t>(protocol, type, name, ipc_key, size);
std::shared_ptr<lv2_event_queue_t> result;
auto make_expr = [&] { return idm::import<lv2_event_queue_t>([&] { return queue; }); };
auto make_expr = [&]() -> const std::shared_ptr<lv2_event_queue_t>&
{
result = idm::make_ptr<lv2_event_queue_t>(protocol, type, name, ipc_key, size);
return result;
};
if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
{
// Not an IPC queue
return make_expr();
make_expr();
return result;
}
// IPC queue
if (ipc_manager<lv2_event_queue_t, u64>::add(ipc_key, make_expr))
{
return queue;
return result;
}
return nullptr;
@ -48,6 +53,16 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::find(u64 ipc_key)
return ipc_manager<lv2_event_queue_t, u64>::get(ipc_key);
}
lv2_event_queue_t::lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol)
, type(type)
, name(name)
, ipc_key(ipc_key)
, size(size)
, id(idm::last_id())
{
}
void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3)
{
verify(HERE), m_sq.empty() || m_events.empty();
@ -61,7 +76,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
// notify waiter; protocol is ignored in current implementation
auto& thread = m_sq.front();
if (type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min)
if (type == SYS_PPU_QUEUE && thread->id_type() == 1)
{
// store event data in registers
auto& ppu = static_cast<ppu_thread&>(*thread);
@ -71,7 +86,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
ppu.gpr[6] = data2;
ppu.gpr[7] = data3;
}
else if (type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min)
else if (type == SYS_SPU_QUEUE && thread->id_type() != 1)
{
// store event data in In_MBox
auto& spu = static_cast<SPUThread&>(*thread);
@ -162,11 +177,11 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
// signal all threads to return CELL_ECANCELED
for (auto& thread : queue->thread_queue(lv2_lock))
{
if (queue->type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min)
if (queue->type == SYS_PPU_QUEUE && thread->id_type() == 1)
{
static_cast<ppu_thread&>(*thread).gpr[3] = 1;
}
else if (queue->type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min)
else if (queue->type == SYS_SPU_QUEUE && thread->id_type() != 1)
{
static_cast<SPUThread&>(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED);
}

View File

@ -73,6 +73,10 @@ class lv2_event_queue_t final
sleep_queue<cpu_thread> m_sq;
public:
static const u32 id_base = 0x8d000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
// Try to make an event queue with specified global key
static std::shared_ptr<lv2_event_queue_t> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
@ -84,17 +88,9 @@ public:
const u64 name;
const u64 ipc_key;
const s32 size;
const u32 id;
const id_value<> id{};
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol)
, type(type)
, name(name)
, ipc_key(ipc_key)
, size(size)
{
}
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
// Send an event
void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3);
@ -120,6 +116,10 @@ public:
struct lv2_event_port_t
{
static const u32 id_base = 0x0e000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL
const u64 name; // passed as event source (generated from id and process id if not set)

View File

@ -31,6 +31,10 @@ struct sys_event_flag_attribute_t
struct lv2_event_flag_t
{
static const u32 id_base = 0x98000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol;
const s32 type;
const u64 name;

View File

@ -96,19 +96,18 @@ struct lv2_fs_mount_point;
struct lv2_fs_object
{
// ID Manager setups
using id_base = 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_min = 3;
static constexpr u32 id_max = 255;
const id_value<> id{};
const u32 id;
// Mount Point
const std::add_pointer_t<lv2_fs_mount_point> mp;
lv2_fs_object(lv2_fs_mount_point* mp)
: mp(mp)
, id(idm::last_id())
{
}

View File

@ -10,6 +10,14 @@
logs::channel sys_interrupt("sys_interrupt", logs::level::notice);
lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)
: thread(thread)
, arg1(arg1)
, arg2(arg2)
, id(idm::last_id())
{
}
void lv2_int_serv_t::exec()
{
thread->cmd_list
@ -149,3 +157,8 @@ void sys_interrupt_thread_eoi(ppu_thread& ppu) // Low-level PPU function example
throw cpu_flag::ret;
}
}
lv2_int_tag_t::lv2_int_tag_t()
: id(idm::last_id())
{
}

View File

@ -6,26 +6,31 @@ class ppu_thread;
struct lv2_int_tag_t
{
const id_value<> id{};
static const u32 id_base = 0x1000a;
static const u32 id_step = 0x10000;
static const u32 id_count = 8192;
const u32 id;
std::shared_ptr<struct lv2_int_serv_t> handler;
lv2_int_tag_t();
};
struct lv2_int_serv_t
{
static const u32 id_base = 0x0b000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const std::shared_ptr<ppu_thread> thread;
const id_value<> id{};
const u32 id;
const u64 arg1;
const u64 arg2;
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)
: thread(thread)
, arg1(arg1)
, arg2(arg2)
{
}
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2);
void exec();
void join(ppu_thread& ppu, lv2_lock_t);

View File

@ -19,6 +19,10 @@ struct sys_lwcond_t
struct lv2_lwcond_t
{
static const u32 id_base = 0x97000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name;
sleep_queue<cpu_thread> sq;

View File

@ -46,6 +46,10 @@ struct sys_lwmutex_t
struct lv2_lwmutex_t
{
static const u32 id_base = 0x95000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol;
const u64 name;

View File

@ -46,6 +46,10 @@ struct sys_page_attr_t
struct lv2_memory_container
{
static const u32 id_base = 0x1; // Wrong?
static const u32 id_step = 0x1;
static const u32 id_count = 16;
const u32 size = 0x10000000; // Amount of "physical" memory in this container
atomic_t<u32> used{}; // Amount of "physical" memory currently used

View File

@ -4,6 +4,10 @@
struct lv2_memory
{
static const u32 id_base = 0x08000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 size; // Memory size
const u32 align; // Alignment required
const u64 flags;

View File

@ -21,6 +21,10 @@ struct sys_mutex_attribute_t
struct lv2_mutex_t
{
static const u32 id_base = 0x85000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const bool recursive;
const u32 protocol;
const u64 name;

View File

@ -229,3 +229,8 @@ s32 sys_prx_stop()
sys_prx.todo("sys_prx_stop()");
return CELL_OK;
}
lv2_prx_t::lv2_prx_t()
: id(idm::last_id())
{
}

View File

@ -76,7 +76,11 @@ struct sys_prx_get_module_list_t
struct lv2_prx_t
{
const id_value<> id{};
static const u32 id_base = 0x23000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 id;
bool is_started = false;
@ -86,6 +90,8 @@ struct lv2_prx_t
vm::ptr<s32(int argc, vm::ptr<void> argv)> start = vm::null;
vm::ptr<s32(int argc, vm::ptr<void> argv)> stop = vm::null;
vm::ptr<s32()> exit = vm::null;
lv2_prx_t();
};
// SysCalls

View File

@ -19,6 +19,10 @@ struct sys_rwlock_attribute_t
struct lv2_rwlock_t
{
static const u32 id_base = 0x88000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name;
const u32 protocol;

View File

@ -19,6 +19,10 @@ struct sys_semaphore_attribute_t
struct lv2_sema_t
{
static const u32 id_base = 0x96000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol;
const s32 max;
const u64 name;

View File

@ -139,6 +139,10 @@ class SPUThread;
struct lv2_spu_group_t
{
static const u32 id_base = 1; // Wrong?
static const u32 id_step = 1;
static const u32 id_count = 8192;
const std::string name;
const u32 num; // SPU Number
const s32 type; // SPU Thread Group Type

View File

@ -24,11 +24,15 @@ class lv2_timer_t final : public named_thread
void on_task() override;
public:
static const u32 id_base = 0x11000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
std::string get_name() const override;
void on_stop() override;
const id_value<> id{};
const u32 id = idm::last_id();
atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state

View File

@ -1,12 +1,11 @@
#include "stdafx.h"
#include "IdManager.h"
DECLARE(idm::g_map);
DECLARE(idm::g_id);
DECLARE(idm::g_mutex);
shared_mutex id_manager::g_mutex;
DECLARE(fxm::g_map);
DECLARE(fxm::g_mutex);
thread_local DECLARE(idm::g_id);
DECLARE(idm::g_map);
DECLARE(fxm::g_vec);
std::vector<id_manager::typeinfo>& id_manager::typeinfo::access()
{
@ -24,20 +23,40 @@ u32 id_manager::typeinfo::add_type()
return ::size32(list) - 1;
}
id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max)
id_manager::id_map::pointer idm::allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count)
{
// Check all IDs starting from "next id"
for (u32 i = 0; i <= max - min; i++)
auto& map = g_map[types.first];
// Assume next ID
u32 next = base;
if (std::size_t _count = map.size())
{
// Fix current ID (wrap around)
if (g_id[tag] < min || g_id[tag] > max) g_id[tag] = min;
// Get ID
const auto r = g_map[tag].emplace(id_manager::id_key{g_id[tag]++, type}, nullptr);
if (r.second)
if (_count >= count)
{
return &*r.first;
return nullptr;
}
const u32 _next = map.rbegin()->first.id() + step;
if (_next > base && _next < base + step * count)
{
next = _next;
}
}
// Check all IDs starting from "next id" (TODO)
for (next; next < base + step * count; next += step)
{
// Get ID
const auto result = map.emplace(id_manager::id_key(next, types.second), nullptr);
if (result.second)
{
// Acknowledge the ID
g_id = next;
return std::addressof(*result.first);
}
}
@ -45,47 +64,61 @@ id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max
return nullptr;
}
std::shared_ptr<void> idm::deallocate_id(u32 tag, u32 id)
id_manager::id_map::pointer idm::find_id(u32 type, u32 id)
{
const auto found = g_map[tag].find(id);
auto& map = g_map[type];
if (found == g_map[tag].end()) return nullptr;
const auto found = map.find(id);
auto ptr = std::move(found->second);
g_map[tag].erase(found);
return ptr;
return found == map.end() ? nullptr : std::addressof(*found);
}
id_manager::id_map::pointer idm::find_id(u32 type, u32 true_type, u32 id)
{
const auto found = g_map[type].find(id);
auto& map = g_map[type];
if (found == g_map[type].end()) return nullptr;
const auto found = map.find(id);
if (true_type != get_type<void>() && found->first.type() != true_type) return nullptr;
return &*found;
return found == map.end() || found->first.type() != true_type ? nullptr : std::addressof(*found);
}
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 tag, u32 id)
std::shared_ptr<void> idm::delete_id(u32 type, u32 id)
{
writer_lock lock(g_mutex);
auto& map = g_map[type];
if (!find_id(type, true_type, id)) return nullptr; // ???
const auto found = map.find(id);
auto&& ptr = deallocate_id(tag, id);
std::shared_ptr<void> result;
g_map[type].erase(id);
if (found != map.end())
{
result = std::move(found->second);
map.erase(found);
}
return ptr;
return result;
}
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 id)
{
auto& map = g_map[type];
const auto found = map.find(id);
std::shared_ptr<void> result;
if (found != map.end() && found->first.type() == true_type)
{
result = std::move(found->second);
map.erase(found);
}
return result;
}
void idm::init()
{
g_map.resize(id_manager::typeinfo::get().size(), {});
g_id.resize(id_manager::typeinfo::get().size(), 0);
g_map.resize(id_manager::typeinfo::get().size());
}
void idm::clear()
@ -101,32 +134,24 @@ void idm::clear()
}
g_map[i].clear();
g_id[i] = 0;
}
}
std::shared_ptr<void> fxm::remove(u32 type)
{
writer_lock lock(g_mutex);
return std::move(g_map[type]);
}
void fxm::init()
{
g_map.resize(id_manager::typeinfo::get().size(), {});
g_vec.resize(id_manager::typeinfo::get().size(), {});
}
void fxm::clear()
{
// Call recorded finalization functions for all IDs
for (std::size_t i = 0; i < g_map.size(); i++)
for (std::size_t i = 0; i < g_vec.size(); i++)
{
if (g_map[i])
if (g_vec[i])
{
id_manager::typeinfo::get()[i].on_stop(g_map[i].get());
id_manager::typeinfo::get()[i].on_stop(g_vec[i].get());
}
g_map[i].reset();
g_vec[i].reset();
}
}

View File

@ -5,28 +5,35 @@
#include <memory>
#include <vector>
#include <unordered_map>
#include <map>
// Mostly helper namespace
// idm/fxm: helper namespace
namespace id_manager
{
// Common global mutex
extern shared_mutex g_mutex;
// Optional ID traits
template<typename T, typename = void>
struct id_traits
{
using tag = void;
static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count");
static constexpr u32 min = 1;
static constexpr u32 max = 0x7fffffff;
static const u32 base = 1; // First ID (N = 0)
static const u32 step = 1; // Any ID: N * id_step + id_base
static const u32 count = 65535; // Limit: N < id_count
static const u32 invalid = 0;
};
template<typename T>
struct id_traits<T, void_t<typename T::id_base, decltype(&T::id_min), decltype(&T::id_max)>>
struct id_traits<T, void_t<decltype(&T::id_base), decltype(&T::id_step), decltype(&T::id_count)>>
{
using tag = typename T::id_base;
static const u32 base = T::id_base;
static const u32 step = T::id_step;
static const u32 count = T::id_count;
static const u32 invalid = base > 0 ? 0 : -1;
static constexpr u32 min = T::id_min;
static constexpr u32 max = T::id_max;
static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range");
};
// Optional object initialization function (called after ID registration)
@ -136,69 +143,30 @@ namespace id_manager
return m_type;
}
bool operator ==(const id_key& rhs) const
operator u32() const
{
return m_value == rhs.m_value;
}
bool operator !=(const id_key& rhs) const
{
return m_value != rhs.m_value;
return m_value;
}
};
// Custom hasher for ID values
struct id_hash final
{
std::size_t operator ()(const id_key& key) const
{
return key.id();
}
};
using id_map = std::unordered_map<id_key, std::shared_ptr<void>, id_hash>;
using id_map = std::map<id_key, std::shared_ptr<void>>;
}
// Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs.
class idm
{
// Rules for ID allocation:
// 0) Individual ID counter may be specified for each type by defining 'using id_base = ...;'
// 1) If no id_base specified, void is assumed.
// 2) g_id[id_base] indicates next ID allocated in g_map.
// 3) g_map[id_base] contains the additional copy of object pointer.
static shared_mutex g_mutex;
// Last allocated ID for constructors
static thread_local u32 g_id;
// Type Index -> ID -> Object. Use global since only one process is supported atm.
static std::vector<id_manager::id_map> g_map;
// Next ID for each category
static std::vector<u32> g_id;
template<typename T>
static inline u32 get_type()
{
return id_manager::typeinfo::get_index<T>();
}
template<typename T>
static inline u32 get_tag()
{
return get_type<typename id_manager::id_traits<T>::tag>();
}
// Update optional ID storage
template<typename T>
static inline auto set_id_value(T* ptr, u32 id) -> decltype(static_cast<void>(std::declval<T&>().id))
{
ptr->id = id;
}
static inline void set_id_value(...)
{
}
// Helper
template<typename F>
struct function_traits;
@ -262,35 +230,44 @@ class idm
};
// Prepare new ID (returns nullptr if out of resources)
static id_manager::id_map::pointer allocate_id(u32 tag, u32 type, u32 min, u32 max);
static id_manager::id_map::pointer allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count);
// Deallocate ID, returns object
static std::shared_ptr<void> deallocate_id(u32 tag, u32 id);
// Remove ID and return the object
static std::shared_ptr<void> delete_id(u32 type, u32 id);
// Remove ID and return the object (check type)
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 id);
// Get ID
static id_manager::id_map::pointer find_id(u32 type, u32 id);
// Get ID (check type)
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
// Allocate new ID and assign the object from the provider()
template<typename T, typename Set, typename F>
template<typename T, typename Type, typename F>
static id_manager::id_map::pointer create_id(F&& provider)
{
writer_lock lock(id_manager::g_mutex);
// Register destructors
id_manager::typeinfo::update<T>();
id_manager::typeinfo::update<typename id_manager::id_traits<T>::tag>();
writer_lock lock(g_mutex);
// Type IDs
std::pair<u32, u32> types(get_type<T>(), get_type<Type>());
if (auto place = allocate_id(get_tag<T>(), get_type<Set>(), id_manager::id_traits<T>::min, id_manager::id_traits<T>::max))
// Allocate new id
if (auto* place = allocate_id(types, id_manager::id_traits<T>::base, id_manager::id_traits<T>::step, id_manager::id_traits<T>::count))
{
try
{
// Get object, store it
place->second = provider();
// Update ID value if required
set_id_value(static_cast<T*>(place->second.get()), place->first.id());
return &*g_map[get_type<T>()].emplace(*place).first;
return place;
}
catch (...)
{
deallocate_id(get_tag<T>(), place->first.id());
delete_id(types.first, place->first.id());
throw;
}
}
@ -298,12 +275,6 @@ class idm
return nullptr;
}
// Get ID (internal)
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
// Remove ID and return the object
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 tag, u32 id);
public:
// Initialize object manager
static void init();
@ -311,6 +282,12 @@ public:
// Remove all objects
static void clear();
// Get last ID
static inline u32 last_id()
{
return g_id;
}
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
template<typename T, typename Make = T, typename... Args>
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<Make>> make_ptr(Args&&... args)
@ -336,7 +313,7 @@ public:
return pair->first.id();
}
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name());
return id_manager::id_traits<T>::invalid;
}
// Add a new ID for an existing object provided (returns new id)
@ -350,7 +327,7 @@ public:
return pair->first.id();
}
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name());
return id_manager::id_traits<T>::invalid;
}
// Add a new ID for an object returned by provider()
@ -368,21 +345,19 @@ public:
}
// Check the ID
template<typename T, typename Get = void>
template<typename T, typename Get = T>
static inline explicit_bool_t check(u32 id)
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
return find_id(get_type<T>(), get_type<Get>(), id) != nullptr;
}
// Check the ID, access object under shared lock
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline explicit_bool_t check(u32 id, F&& func, int = 0)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -391,17 +366,15 @@ public:
return false;
}
func(*static_cast<pointer_type*>(found->second.get()));
func(*static_cast<Get*>(found->second.get()));
return true;
}
// Check the ID, access object under reader lock, propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline return_pair<bool, FRT> check(u32 id, F&& func)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -410,14 +383,14 @@ public:
return {false};
}
return {true, func(*static_cast<pointer_type*>(found->second.get()))};
return {true, func(*static_cast<Get*>(found->second.get()))};
}
// Get the object
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
template<typename T, typename Get = T, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
static inline std::shared_ptr<Made> get(u32 id)
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -430,13 +403,12 @@ public:
}
// Get the object, access object under reader lock
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func, int = 0)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
using result_type = std::shared_ptr<pointer_type>;
using result_type = std::shared_ptr<Get>;
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -445,7 +417,7 @@ public:
return result_type{nullptr};
}
const auto ptr = static_cast<pointer_type*>(found->second.get());
const auto ptr = static_cast<Get*>(found->second.get());
func(*ptr);
@ -453,13 +425,12 @@ public:
}
// Get the object, access object under reader lock, propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
using result_type = return_pair<pointer_type, FRT>;
using result_type = return_pair<Get, FRT>;
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -468,7 +439,7 @@ public:
return result_type{nullptr};
}
const auto ptr = static_cast<pointer_type*>(found->second.get());
const auto ptr = static_cast<Get*>(found->second.get());
return result_type{{found->second, ptr}, func(*ptr)};
}
@ -477,7 +448,7 @@ public:
template<typename... Types, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::void_type>
static inline u32 select(F&& func, int = 0)
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
u32 result = 0;
@ -500,7 +471,7 @@ public:
using object_type = typename function_traits<FT>::object_type;
using result_type = return_pair<object_type, FRT>;
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
for (u32 type : { get_type<Types>()... })
{
@ -517,10 +488,10 @@ public:
}
// Get count of objects
template<typename T, typename Get = void>
template<typename T, typename Get = T>
static inline u32 get_count()
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
if (std::is_void<Get>::value)
{
@ -541,10 +512,10 @@ public:
}
// Remove the ID
template<typename T, typename Get = void>
template<typename T, typename Get = T>
static inline explicit_bool_t remove(u32 id)
{
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
auto ptr = delete_id(get_type<T>(), get_type<Get>(), id);
if (LIKELY(ptr))
{
@ -555,29 +526,28 @@ public:
}
// Remove the ID and return the object
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
static inline std::shared_ptr<Made> withdraw(u32 id)
template<typename T, typename Get = T>
static inline std::shared_ptr<Get> withdraw(u32 id)
{
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
auto ptr = delete_id(get_type<T>(), get_type<Get>(), id);
if (LIKELY(ptr))
{
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
}
return {ptr, static_cast<Made*>(ptr.get())};
return {ptr, static_cast<Get*>(ptr.get())};
}
// Remove the ID after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func, int = 0)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
using result_type = std::shared_ptr<pointer_type>;
using result_type = std::shared_ptr<Get>;
std::shared_ptr<void> ptr;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -586,29 +556,28 @@ public:
return result_type{nullptr};
}
func(*static_cast<pointer_type*>(found->second.get()));
func(*static_cast<Get*>(found->second.get()));
ptr = deallocate_id(get_tag<T>(), id);
ptr = delete_id(get_type<T>(), id);
g_map[get_type<T>()].erase(id);
}
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return result_type{ptr, static_cast<pointer_type*>(ptr.get())};
return result_type{ptr, static_cast<Get*>(ptr.get())};
}
// Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func)
{
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>;
using result_type = return_pair<pointer_type, FRT>;
using result_type = return_pair<Get, FRT>;
std::shared_ptr<void> ptr;
FRT ret;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -617,7 +586,7 @@ public:
return result_type{nullptr};
}
const auto _ptr = static_cast<pointer_type*>(found->second.get());
const auto _ptr = static_cast<Get*>(found->second.get());
ret = func(*_ptr);
@ -626,14 +595,14 @@ public:
return result_type{{found->second, _ptr}, std::move(ret)};
}
ptr = deallocate_id(get_tag<T>(), id);
ptr = delete_id(get_type<T>(), id);
g_map[get_type<T>()].erase(id);
}
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return result_type{{ptr, static_cast<pointer_type*>(ptr.get())}, std::move(ret)};
return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
}
};
@ -641,9 +610,7 @@ public:
class fxm
{
// Type Index -> Object. Use global since only one process is supported atm.
static std::vector<std::shared_ptr<void>> g_map;
static shared_mutex g_mutex;
static std::vector<std::shared_ptr<void>> g_vec;
template<typename T>
static inline u32 get_type()
@ -651,8 +618,6 @@ class fxm
return id_manager::typeinfo::get_index<T>();
}
static std::shared_ptr<void> remove(u32 type);
public:
// Initialize object manager
static void init();
@ -668,13 +633,13 @@ public:
std::shared_ptr<T> ptr;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
if (!g_map[get_type<T>()])
if (!g_vec[get_type<T>()])
{
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr;
g_vec[get_type<T>()] = ptr;
}
}
@ -696,12 +661,12 @@ public:
std::shared_ptr<T> ptr;
std::shared_ptr<void> old;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
old = std::move(g_map[get_type<T>()]);
old = std::move(g_vec[get_type<T>()]);
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr;
g_vec[get_type<T>()] = ptr;
}
if (old)
@ -721,13 +686,13 @@ public:
std::shared_ptr<T> ptr;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
if (!g_map[get_type<T>()])
if (!g_vec[get_type<T>()])
{
ptr = provider();
g_map[get_type<T>()] = ptr;
g_vec[get_type<T>()] = ptr;
}
}
@ -749,12 +714,12 @@ public:
std::shared_ptr<T> ptr;
std::shared_ptr<void> old;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
old = std::move(g_map[get_type<T>()]);
old = std::move(g_vec[get_type<T>()]);
ptr = provider();
g_map[get_type<T>()] = ptr;
g_vec[get_type<T>()] = ptr;
}
if (old)
@ -774,9 +739,9 @@ public:
std::shared_ptr<T> ptr;
{
writer_lock lock(g_mutex);
writer_lock lock(id_manager::g_mutex);
if (auto& value = g_map[get_type<T>()])
if (auto& value = g_vec[get_type<T>()])
{
return{ value, static_cast<T*>(value.get()) };
}
@ -784,7 +749,7 @@ public:
{
ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr;
g_vec[get_type<T>()] = ptr;
}
}
@ -797,18 +762,18 @@ public:
template<typename T>
static inline explicit_bool_t check()
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
return g_map[get_type<T>()].operator bool();
return g_vec[get_type<T>()].operator bool();
}
// Get the object (returns nullptr if it doesn't exist)
template<typename T>
static inline std::shared_ptr<T> get()
{
reader_lock lock(g_mutex);
reader_lock lock(id_manager::g_mutex);
auto& ptr = g_map[get_type<T>()];
auto& ptr = g_vec[get_type<T>()];
return{ ptr, static_cast<T*>(ptr.get()) };
}
@ -817,7 +782,11 @@ public:
template<typename T>
static inline explicit_bool_t remove()
{
auto ptr = remove(get_type<T>());
std::shared_ptr<void> ptr;
{
writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]);
}
if (ptr)
{
@ -831,7 +800,11 @@ public:
template<typename T>
static inline std::shared_ptr<T> withdraw()
{
auto ptr = remove(get_type<T>());
std::shared_ptr<void> ptr;
{
writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]);
}
if (ptr)
{

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/IdManager.h"
#include "Emu/System.h"
#include "ARMv7Thread.h"
@ -94,7 +95,7 @@ ARMv7Thread::~ARMv7Thread()
}
ARMv7Thread::ARMv7Thread(const std::string& name, u32 prio, u32 stack)
: cpu_thread()
: cpu_thread(idm::last_id())
, m_name(name)
, prio(prio)
, stack_addr(vm::alloc(stack, vm::main))

View File

@ -14,6 +14,10 @@ enum ARMv7InstructionSet
class ARMv7Thread final : public cpu_thread
{
public:
static const u32 id_base = 1;
static const u32 id_step = 2;
static const u32 id_count = 32767;
virtual std::string get_name() const override;
virtual std::string dump() const override;
virtual void cpu_task() override;

View File

@ -808,6 +808,10 @@ s32 sceKernelWaitMultipleEventsCB(vm::ptr<SceKernelWaitEvent> pWaitEventList, s3
struct psp2_event_flag final
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
struct alignas(8) ctrl_t
{
u32 waiters;

View File

@ -496,6 +496,10 @@ struct SceKernelSemaInfo
struct psp2_semaphore
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter
@ -536,6 +540,10 @@ struct SceKernelMutexInfo
struct psp2_mutex
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter
@ -596,6 +604,10 @@ struct SceKernelCondInfo
struct psp2_cond
{
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter

View File

@ -481,7 +481,7 @@ s32 error_code::error_report(const fmt_type_info* sup, u64 arg)
if (auto thread = get_current_cpu_thread())
{
if (g_system == system_type::ps3 && thread->id >= ppu_thread::id_min)
if (g_system == system_type::ps3 && thread->id_type() == 1)
{
if (auto func = static_cast<ppu_thread*>(thread)->last_function)
{

View File

@ -61,7 +61,7 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_t
s_panel_margin_x->Add(s_panel_margin_y);
s_panel_margin_x->AddSpacer(12);
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0;
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview));
t2_instr->SetValue(wxString::Format("%08x", vm::ps3::read32(cpu_offset + pc).value()));

View File

@ -25,7 +25,7 @@ u32 InterpreterDisAsmFrame::GetPc() const
{
switch (g_system)
{
case system_type::ps3: return cpu->id >= ppu_thread::id_min ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc;
case system_type::ps3: return cpu->id_type() == 1 ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc;
case system_type::psv: return static_cast<ARMv7Thread*>(cpu)->PC;
}
@ -140,7 +140,7 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{
case system_type::ps3:
{
if (cpu->id >= ppu_thread::id_min)
if (cpu->id_type() == 1)
{
m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode);
}
@ -250,7 +250,7 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
}
else
{
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0;
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
m_disasm->offset = (u8*)vm::base(cpu_offset);
for (uint i = 0, count = 4; i<m_item_count; ++i, m_pc += count)
{

View File

@ -58,7 +58,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
{
case system_type::ps3:
{
if (_cpu->id >= ppu_thread::id_min)
if (_cpu->id_type() == 1)
{
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("GPR[%d]", i));
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("FPR[%d]", i));
@ -89,7 +89,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string value = fmt::ToUTF8(t2_value->GetValue());
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min)
if (g_system == system_type::ps3 && cpu->id_type() == 1)
{
auto& ppu = *static_cast<ppu_thread*>(cpu);
@ -134,7 +134,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
{
}
}
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min)
else if (g_system == system_type::ps3 && cpu->id_type() != 1)
{
auto& spu = *static_cast<SPUThread*>(cpu);
@ -169,7 +169,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string str;
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min)
if (g_system == system_type::ps3 && cpu->id_type() == 1)
{
auto& ppu = *static_cast<ppu_thread*>(cpu);
@ -185,7 +185,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
if (reg == "LR") str = fmt::format("%016llx", ppu.lr);
if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr);
}
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min)
else if (g_system == system_type::ps3 && cpu->id_type() != 1)
{
auto& spu = *static_cast<SPUThread*>(cpu);