Minor cleanup

This commit is contained in:
Nekotekina 2015-07-04 22:23:10 +03:00
parent 3064cf8101
commit 22e1da5e76
19 changed files with 166 additions and 249 deletions

View File

@ -1307,6 +1307,7 @@ void thread_t::start(std::function<std::string()> name, std::function<void()> fu
}
//ctrl->set_current(false);
vm::reservation_free();
g_thread_count--;

View File

@ -81,7 +81,7 @@ void armv7_free_tls(u32 thread)
}
ARMv7Thread::ARMv7Thread(const std::string& name)
: CPUThread(CPU_THREAD_ARMv7, name, [this]{ return fmt::format("%s[0x%x] Thread (%s)[0x%08x]", GetTypeString(), GetId(), GetName(), PC); })
: CPUThread(CPU_THREAD_ARMv7, name, WRAP_EXPR(fmt::format("ARMv7[0x%x] Thread (%s)[0x%08x]", GetId(), GetName(), PC)))
, ARMv7Context({})
{
}

View File

@ -16,7 +16,7 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
, m_type(type)
, m_name(name)
{
start(thread_name, [this]
start(std::move(thread_name), [this]
{
SendDbgCommand(DID_CREATE_THREAD, this);

View File

@ -78,7 +78,7 @@ std::shared_ptr<RawSPUThread> CPUThreadManager::NewRawSPUThread()
{
if (m_raw_spu[i].expired())
{
m_raw_spu[i] = result = Emu.GetIdManager().make_ptr<RawSPUThread>("RawSPU " + std::to_string(i), i);
m_raw_spu[i] = result = Emu.GetIdManager().make_ptr<RawSPUThread>(std::to_string(i), i);
break;
}
}

View File

@ -491,7 +491,7 @@ void fill_ppu_exec_map(u32 addr, u32 size)
}
PPUThread::PPUThread(const std::string& name)
: CPUThread(CPU_THREAD_PPU, name, [this]{ return fmt::format("%s[0x%x] Thread (%s)[0x%08x]", GetTypeString(), GetId(), GetName(), PC); })
: CPUThread(CPU_THREAD_PPU, name, WRAP_EXPR(fmt::format("PPU[0x%x] Thread (%s)[0x%08x]", GetId(), GetName(), PC)))
{
InitRotateMask();
}

View File

@ -9,7 +9,7 @@
thread_local spu_mfc_arg_t raw_spu_mfc[8] = {};
RawSPUThread::RawSPUThread(const std::string& name, u32 index)
: SPUThread(CPU_THREAD_RAW_SPU, name, index, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index)
: SPUThread(CPU_THREAD_RAW_SPU, name, WRAP_EXPR(fmt::format("RawSPU[0x%x] Thread (%s)[0x%08x]", GetId(), GetName(), PC)), index, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index)
{
Memory.Map(offset, 0x40000);
}
@ -23,18 +23,16 @@ RawSPUThread::~RawSPUThread()
void RawSPUThread::start()
{
bool do_start;
status.atomic_op([&do_start](u32& status)
const bool do_start = status.atomic_op([](u32& status) -> bool
{
if (status & SPU_STATUS_RUNNING)
{
do_start = false;
return false;
}
else
{
status = SPU_STATUS_RUNNING;
do_start = true;
return true;
}
});
@ -166,6 +164,7 @@ bool RawSPUThread::WriteReg(const u32 addr, const u32 value)
case SPU_In_MBox_offs:
{
ch_in_mbox.push_uncond(value);
cv.notify_one();
return true;
}

View File

@ -57,15 +57,15 @@ public:
}
g_spu_inter_func_list;
SPUThread::SPUThread(CPUThreadType type, const std::string& name, u32 index, u32 offset)
: CPUThread(type, name, [this]{ return fmt::format("%s[0x%x] Thread (%s)[0x%08x]", GetTypeString(), GetId(), GetName(), PC); })
SPUThread::SPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name, u32 index, u32 offset)
: CPUThread(type, name, std::move(thread_name))
, index(index)
, offset(offset)
{
}
SPUThread::SPUThread(const std::string& name, u32 index)
: CPUThread(CPU_THREAD_SPU, name, [this]{ return fmt::format("%s[0x%x] Thread (%s)[0x%08x]", GetTypeString(), GetId(), GetName(), PC); })
: CPUThread(CPU_THREAD_SPU, name, WRAP_EXPR(fmt::format("SPU[0x%x] Thread (%s)[0x%08x]", GetId(), GetName(), PC)))
, index(index)
, offset(Memory.MainMem.AllocAlign(0x40000))
{

View File

@ -571,6 +571,8 @@ public:
ch_snr2.push_uncond(value);
}
}
cv.notify_one();
}
void do_dma_transfer(u32 cmd, spu_mfc_arg_t args);
@ -630,7 +632,7 @@ public:
std::function<void(SPUThread& SPU)> m_custom_task;
protected:
SPUThread(CPUThreadType type, const std::string& name, u32 index, u32 offset);
SPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name, u32 index, u32 offset);
public:
SPUThread(const std::string& name, u32 index);

View File

@ -22,11 +22,13 @@ public:
const std::shared_ptr<void> data;
const std::type_info& info;
const u32 type;
const u32 id;
template<typename T> force_inline ID_data_t(std::shared_ptr<T> data, u32 type)
template<typename T> force_inline ID_data_t(std::shared_ptr<T> data, u32 type, u32 id)
: data(std::move(data))
, info(typeid(T))
, type(type)
, id(id)
{
}
@ -34,6 +36,7 @@ public:
: data(right.data)
, info(right.info)
, type(right.type)
, id(right.id)
{
}
@ -43,6 +46,7 @@ public:
: data(std::move(const_cast<std::shared_ptr<void>&>(right.data)))
, info(right.info)
, type(right.type)
, id(right.id)
{
}
@ -101,9 +105,9 @@ public:
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
m_id_map.emplace(m_cur_id++, ID_data_t(ptr, type));
m_id_map.emplace(m_cur_id, ID_data_t(ptr, type, m_cur_id));
return std::move(ptr);
return m_cur_id++, std::move(ptr);
}
// add new ID of specified type with specified constructor arguments (returns id)
@ -113,7 +117,7 @@ public:
const u32 type = ID_type<T>::type;
m_id_map.emplace(m_cur_id, ID_data_t(std::make_shared<T>(std::forward<Args>(args)...), type));
m_id_map.emplace(m_cur_id, ID_data_t(std::make_shared<T>(std::forward<Args>(args)...), type, m_cur_id));
return m_cur_id++;
}

View File

@ -82,7 +82,7 @@ namespace vm
{
atomic<const thread_ctrl_t*> m_owner{};
std::condition_variable m_cv;
std::mutex m_cv_mutex;
std::mutex m_mutex;
public:
reservation_mutex_t()
@ -95,18 +95,18 @@ namespace vm
{
auto owner = get_current_thread_ctrl();
std::unique_lock<std::mutex> lock(m_mutex, std::defer_lock);
while (auto old = m_owner.compare_and_swap(nullptr, owner))
{
std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
m_cv.wait_for(cv_lock, std::chrono::milliseconds(1));
if (old == owner)
{
throw EXCEPTION("Deadlock");
}
old = nullptr;
if (!lock) lock.lock();
m_cv.wait_for(lock, std::chrono::milliseconds(1));
}
do_notify = true;
@ -195,7 +195,7 @@ namespace vm
return _reservation_break(addr);
}
bool reservation_acquire(void* data, u32 addr, u32 size, const std::function<void()>& callback)
bool reservation_acquire(void* data, u32 addr, u32 size, std::function<void()> callback)
{
//const auto stamp0 = get_time();
@ -232,7 +232,7 @@ namespace vm
g_reservation_addr = addr;
g_reservation_size = size;
g_reservation_owner = get_current_thread_ctrl();
g_reservation_cb = callback;
g_reservation_cb = std::move(callback);
// copy data
memcpy(data, vm::get_ptr(addr), size);
@ -243,7 +243,7 @@ namespace vm
bool reservation_acquire_no_cb(void* data, u32 addr, u32 size)
{
return reservation_acquire(data, addr, size);
return reservation_acquire(data, addr, size, nullptr);
}
bool reservation_update(u32 addr, const void* data, u32 size)
@ -303,10 +303,10 @@ namespace vm
void reservation_free()
{
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
if (g_reservation_owner == get_current_thread_ctrl())
{
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
_reservation_break(g_reservation_addr);
}
}

View File

@ -35,7 +35,7 @@ namespace vm
// break the reservation, return true if it was successfully broken
bool reservation_break(u32 addr);
// read memory and reserve it for further atomic update, return true if the previous reservation was broken
bool reservation_acquire(void* data, u32 addr, u32 size, const std::function<void()>& callback = nullptr);
bool reservation_acquire(void* data, u32 addr, u32 size, std::function<void()> callback = nullptr);
// same as reservation_acquire but does not have the callback argument
// used by the PPU LLVM JIT since creating a std::function object in LLVM IR is too complicated
bool reservation_acquire_no_cb(void* data, u32 addr, u32 size);

View File

@ -9,44 +9,36 @@
#include "Emu/CPU/CPUThreadManager.h"
#include "Callback.h"
void CallbackManager::Register(std::function<s32(PPUThread& PPU)> func)
void CallbackManager::Register(check_cb_t func)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_cb_list.push_back([=](CPUThread& CPU) -> s32
{
if (CPU.GetType() != CPU_THREAD_PPU) throw EXCEPTION("PPU thread expected");
return func(static_cast<PPUThread&>(CPU));
});
m_check_cb.emplace(std::move(func));
}
void CallbackManager::Async(std::function<void(CPUThread& CPU)> func)
void CallbackManager::Async(async_cb_t func)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_async_list.push_back([=](CPUThread& CPU)
{
func(CPU);
});
m_async_cb.emplace(std::move(func));
m_cv.notify_one();
}
bool CallbackManager::Check(CPUThread& CPU, s32& result)
CallbackManager::check_cb_t CallbackManager::Check()
{
std::function<s32(CPUThread& CPU)> func;
std::lock_guard<std::mutex> lock(m_mutex);
if (m_check_cb.size())
{
std::lock_guard<std::mutex> lock(m_mutex);
check_cb_t func = std::move(m_check_cb.front());
if (m_cb_list.size())
{
func = std::move(m_cb_list.front());
m_cb_list.erase(m_cb_list.begin());
}
m_check_cb.pop();
return func;
}
return func ? result = func(CPU), true : false;
return nullptr;
}
void CallbackManager::Init()
@ -57,26 +49,25 @@ void CallbackManager::Init()
{
std::unique_lock<std::mutex> lock(m_mutex);
while (!CPU.CheckStatus())
while (true)
{
std::function<void(CPUThread& CPU)> func;
if (m_async_list.size())
{
func = std::move(m_async_list.front());
m_async_list.erase(m_async_list.begin());
}
if (func)
{
if (lock) lock.unlock();
func(*m_cb_thread);
continue;
}
CHECK_EMU_STATUS;
if (!lock) lock.lock();
if (m_async_cb.size())
{
async_cb_t func = std::move(m_async_cb.front());
m_async_cb.pop();
if (lock) lock.unlock();
func(CPU);
continue;
}
m_cv.wait_for(lock, std::chrono::milliseconds(1));
}
};
@ -109,46 +100,9 @@ void CallbackManager::Clear()
{
std::lock_guard<std::mutex> lock(m_mutex);
m_cb_list.clear();
m_async_list.clear();
m_pause_cb_list.clear();
m_check_cb = {};
m_async_cb = {};
m_cb_thread.reset();
}
u64 CallbackManager::AddPauseCallback(std::function<PauseResumeCB> func)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_pause_cb_list.push_back({ func, next_tag });
return next_tag++;
}
void CallbackManager::RemovePauseCallback(const u64 tag)
{
std::lock_guard<std::mutex> lock(m_mutex);
for (auto& data : m_pause_cb_list)
{
if (data.tag == tag)
{
m_pause_cb_list.erase(m_pause_cb_list.begin() + (&data - m_pause_cb_list.data()));
return;
}
}
assert(!"CallbackManager()::RemovePauseCallback(): tag not found");
}
void CallbackManager::RunPauseCallbacks(const bool is_paused)
{
std::lock_guard<std::mutex> lock(m_mutex);
for (auto& data : m_pause_cb_list)
{
if (data.cb)
{
data.cb(is_paused);
}
}
}

View File

@ -1,66 +1,31 @@
#pragma once
class CPUThread;
class PPUThread;
typedef void(PauseResumeCB)(bool is_paused);
class CallbackManager
{
using check_cb_t = std::function<s32(CPUThread&)>;
using async_cb_t = std::function<void(CPUThread&)>;
std::mutex m_mutex;
std::condition_variable m_cv;
std::vector<std::function<s32(CPUThread&)>> m_cb_list;
std::vector<std::function<void(CPUThread&)>> m_async_list;
std::queue<check_cb_t> m_check_cb;
std::queue<async_cb_t> m_async_cb;
std::shared_ptr<CPUThread> m_cb_thread;
struct PauseResumeCBS
{
std::function<PauseResumeCB> cb;
u64 tag;
};
u64 next_tag; // not initialized, only increased
std::vector<PauseResumeCBS> m_pause_cb_list;
public:
void Register(std::function<s32(PPUThread& CPU)> func); // register callback (called in Check() method)
// register checked callback (accepts CPUThread&, returns s32)
void Register(check_cb_t func);
void Async(std::function<void(CPUThread& CPU)> func); // register callback for callback thread (called immediately)
// register async callback, called in callback thread (accepts CPUThread&)
void Async(async_cb_t func);
bool Check(CPUThread& CPU, s32& result); // call one callback registered by Register() method
// get one registered callback
check_cb_t Check();
void Init();
void Clear();
u64 AddPauseCallback(std::function<PauseResumeCB> func); // register callback for pausing/resuming emulation events
void RemovePauseCallback(const u64 tag); // unregister callback (uses the result of AddPauseCallback() function)
void RunPauseCallbacks(const bool is_paused);
};
class PauseCallbackRegisterer
{
CallbackManager& cb_manager;
u64 cb_tag;
private:
PauseCallbackRegisterer() = delete;
PauseCallbackRegisterer(const PauseCallbackRegisterer& right) = delete;
PauseCallbackRegisterer(PauseCallbackRegisterer&& right) = delete;
PauseCallbackRegisterer& operator =(const PauseCallbackRegisterer& right) = delete;
PauseCallbackRegisterer& operator =(PauseCallbackRegisterer&& right) = delete;
public:
PauseCallbackRegisterer(CallbackManager& cb_manager, const std::function<PauseResumeCB>& func)
: cb_manager(cb_manager)
, cb_tag(cb_manager.AddPauseCallback(func))
{
}
~PauseCallbackRegisterer()
{
cb_manager.RemovePauseCallback(cb_tag);
}
};

View File

@ -35,7 +35,6 @@ s32 cellAudioInit()
}
// reset variables
g_audio.start_time = 0;
g_audio.counter = 0;
g_audio.keys.clear();
g_audio.start_time = get_system_time();
@ -137,22 +136,6 @@ s32 cellAudioInit()
Emu.GetAudioManager().GetAudioOut().Quit();
});
u64 last_pause_time;
std::atomic<u64> added_time(0);
PauseCallbackRegisterer pcb(Emu.GetCallbackManager(), [&last_pause_time, &added_time](bool is_paused)
{
if (is_paused)
{
last_pause_time = get_system_time();
}
else
{
added_time += get_system_time() - last_pause_time;
g_audio.thread.cv.notify_one();
}
});
while (g_audio.state.load() == AUDIO_STATE_INITIALIZED && !Emu.IsStopped())
{
if (Emu.IsPaused())
@ -161,40 +144,32 @@ s32 cellAudioInit()
continue;
}
if (added_time)
{
g_audio.start_time += added_time.exchange(0);
}
const u64 stamp0 = get_system_time();
const u64 time_pos = stamp0 - g_audio.start_time - Emu.GetPauseTime();
// TODO: send beforemix event (in ~2,6 ms before mixing)
// precise time of sleeping: 5,(3) ms (or 256/48000 sec)
const u64 expected_time = g_audio.counter * AUDIO_SAMPLES * MHZ / 48000;
if (expected_time >= stamp0 - g_audio.start_time)
if (expected_time >= time_pos)
{
g_audio.thread.cv.wait_for(lock, std::chrono::milliseconds(1));
continue;
}
// crutch to hide giant lags caused by debugger
const u64 missed_time = stamp0 - g_audio.start_time - expected_time;
if (missed_time > AUDIO_SAMPLES * MHZ / 48000)
{
cellAudio.Notice("%f ms adjusted", (float)missed_time / 1000);
g_audio.start_time += missed_time;
}
//// crutch to hide giant lags caused by debugger
//const u64 missed_time = time_pos - expected_time;
//if (missed_time > AUDIO_SAMPLES * MHZ / 48000)
//{
// cellAudio.Notice("%f ms adjusted", (float)missed_time / 1000);
// g_audio.start_time += missed_time;
//}
g_audio.counter++;
const u32 out_pos = g_audio.counter % BUFFER_NUM;
//if (Emu.IsPaused())
//{
// continue;
//}
bool first_mix = true;
// mixing:
@ -427,7 +402,7 @@ s32 cellAudioInit()
}
//LOG_NOTICE(HLE, "Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
//stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
//time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
}
});
@ -679,7 +654,7 @@ s32 cellAudioGetPortTimestamp(u32 portNum, u64 tag, vm::ptr<u64> stamp)
std::lock_guard<std::mutex> lock(g_audio.thread.mutex);
*stamp = g_audio.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000;
*stamp = g_audio.start_time + Emu.GetPauseTime() + (port.counter + (tag - port.tag)) * 256000000 / 48000;
return CELL_OK;
}

View File

@ -146,9 +146,9 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialog
{
const s32 status = g_msg_dialog->status;
Emu.GetCallbackManager().Register([=](PPUThread& PPU) -> s32
Emu.GetCallbackManager().Register([=](CPUThread& CPU) -> s32
{
callback(PPU, status, userData);
callback(static_cast<PPUThread&>(CPU), status, userData);
return CELL_OK;
});
}

View File

@ -302,8 +302,8 @@ struct sys_callback
{
vm::ptr<CellSysutilCallback> func;
vm::ptr<void> arg;
} g_sys_callback[4];
}
g_sys_callback[4];
void sysutilSendSystemCommand(u64 status, u64 param)
{
@ -312,9 +312,9 @@ void sysutilSendSystemCommand(u64 status, u64 param)
{
if (cb.func)
{
Emu.GetCallbackManager().Register([=](PPUThread& PPU) -> s32
Emu.GetCallbackManager().Register([=](CPUThread& CPU) -> s32
{
cb.func(PPU, status, param, cb.arg);
cb.func(static_cast<PPUThread&>(CPU), status, param, cb.arg);
return CELL_OK;
});
}
@ -325,26 +325,16 @@ s32 cellSysutilCheckCallback(PPUThread& CPU)
{
cellSysutil.Log("cellSysutilCheckCallback()");
s32 res;
u32 count = 0;
while (Emu.GetCallbackManager().Check(CPU, res))
while (auto func = Emu.GetCallbackManager().Check())
{
CHECK_EMU_STATUS;
count++;
if (res)
if (s32 res = func(CPU))
{
return res;
}
}
if (!count && !g_sys_callback[0].func && !g_sys_callback[1].func && !g_sys_callback[2].func && !g_sys_callback[3].func)
{
LOG_WARNING(TTY, "System warning: no callback registered\n");
}
return CELL_OK;
}

View File

@ -694,6 +694,7 @@ s32 sys_spu_thread_write_spu_mb(u32 id, u32 value)
}
thread->ch_in_mbox.push_uncond(value);
thread->cv.notify_one();
return CELL_OK;
}

View File

@ -37,8 +37,8 @@ static const std::string& BreakPointsDBName = "BreakPoints.dat";
static const u16 bpdb_version = 0x1000;
extern std::atomic<u32> g_thread_count;
extern u64 get_system_time();
extern void finalize_ppu_exec_map();
extern void finalize_psv_modules();
extern void clear_all_psv_objects();
@ -64,17 +64,6 @@ Emulator::Emulator()
Emulator::~Emulator()
{
delete m_thread_manager;
delete m_pad_manager;
delete m_keyboard_manager;
delete m_mouse_manager;
delete m_id_manager;
delete m_gs_manager;
delete m_audio_manager;
delete m_callback_manager;
delete m_event_manager;
delete m_module_manager;
delete m_vfs;
}
void Emulator::Init()
@ -144,7 +133,11 @@ void Emulator::Load()
GetModuleManager().Init();
if (!fs::is_file(m_path)) return;
if (!fs::is_file(m_path))
{
m_status = Stopped;
return;
}
const std::string elf_dir = m_path.substr(0, m_path.find_last_of("/\\", std::string::npos, 2) + 1);
@ -177,6 +170,7 @@ void Emulator::Load()
if (!DecryptSelf(m_path, elf_dir + full_name))
{
m_status = Stopped;
return;
}
}
@ -238,12 +232,14 @@ void Emulator::Load()
if (!f.IsOpened())
{
LOG_ERROR(LOADER, "Opening '%s' failed", m_path.c_str());
m_status = Stopped;
return;
}
if (!m_loader.load(f))
{
LOG_ERROR(LOADER, "Loading '%s' failed", m_path.c_str());
m_status = Stopped;
vm::close();
return;
}
@ -276,6 +272,8 @@ void Emulator::Run()
SendDbgCommand(DID_START_EMU);
m_pause_start_time = 0;
m_pause_amend_time = 0;
m_status = Running;
GetCPU().Exec();
@ -284,28 +282,48 @@ void Emulator::Run()
void Emulator::Pause()
{
if (!IsRunning()) return;
const u64 start = get_system_time();
// try to set Paused status
if (!sync_bool_compare_and_swap(&m_status, Running, Paused))
{
return;
}
// update pause start time
if (m_pause_start_time.exchange(start))
{
LOG_ERROR(GENERAL, "Pause(): Concurrent access");
}
SendDbgCommand(DID_PAUSE_EMU);
if (sync_bool_compare_and_swap(&m_status, Running, Paused))
for (auto& t : GetCPU().GetAllThreads())
{
for (auto& t : GetCPU().GetAllThreads())
{
t->Sleep(); // trigger status check
}
SendDbgCommand(DID_PAUSED_EMU);
GetCallbackManager().RunPauseCallbacks(true);
t->Sleep(); // trigger status check
}
SendDbgCommand(DID_PAUSED_EMU);
}
void Emulator::Resume()
{
if (!IsPaused()) return;
SendDbgCommand(DID_RESUME_EMU);
// try to resume
if (!sync_bool_compare_and_swap(&m_status, Paused, Running))
{
return;
}
m_status = Running;
if (const u64 time = m_pause_start_time.exchange(0))
{
m_pause_amend_time += get_system_time() - time;
}
else
{
LOG_ERROR(GENERAL, "Resume(): Concurrent access");
}
SendDbgCommand(DID_RESUME_EMU);
for (auto& t : GetCPU().GetAllThreads())
{
@ -313,15 +331,16 @@ void Emulator::Resume()
}
SendDbgCommand(DID_RESUMED_EMU);
GetCallbackManager().RunPauseCallbacks(false);
}
extern std::map<u32, std::string> g_armv7_dump;
void Emulator::Stop()
{
if(IsStopped()) return;
if (sync_lock_test_and_set(&m_status, Stopped) == Stopped)
{
return;
}
SendDbgCommand(DID_STOP_EMU);

View File

@ -54,6 +54,9 @@ class Emulator
volatile u32 m_status;
uint m_mode;
std::atomic<u64> m_pause_start_time; // set when paused
std::atomic<u64> m_pause_amend_time; // increased when resumed
u32 m_rsx_callback;
u32 m_cpu_thr_stop;
@ -62,17 +65,17 @@ class Emulator
std::mutex m_core_mutex;
CPUThreadManager* m_thread_manager;
PadManager* m_pad_manager;
KeyboardManager* m_keyboard_manager;
MouseManager* m_mouse_manager;
ID_manager* m_id_manager;
GSManager* m_gs_manager;
AudioManager* m_audio_manager;
CallbackManager* m_callback_manager;
EventManager* m_event_manager;
ModuleManager* m_module_manager;
VFS* m_vfs;
std::unique_ptr<CPUThreadManager> m_thread_manager;
std::unique_ptr<PadManager> m_pad_manager;
std::unique_ptr<KeyboardManager> m_keyboard_manager;
std::unique_ptr<MouseManager> m_mouse_manager;
std::unique_ptr<ID_manager> m_id_manager;
std::unique_ptr<GSManager> m_gs_manager;
std::unique_ptr<AudioManager> m_audio_manager;
std::unique_ptr<CallbackManager> m_callback_manager;
std::unique_ptr<EventManager> m_event_manager;
std::unique_ptr<ModuleManager> m_module_manager;
std::unique_ptr<VFS> m_vfs;
EmuInfo m_info;
loader::loader m_loader;
@ -117,8 +120,12 @@ public:
m_emu_path = path;
}
std::mutex& GetCoreMutex() { return m_core_mutex; }
u64 GetPauseTime()
{
return m_pause_amend_time;
}
std::mutex& GetCoreMutex() { return m_core_mutex; }
CPUThreadManager& GetCPU() { return *m_thread_manager; }
PadManager& GetPadManager() { return *m_pad_manager; }
KeyboardManager& GetKeyboardManager() { return *m_keyboard_manager; }