mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
Merge pull request #965 from Nekotekina/master
cellAudio update, thread_t
This commit is contained in:
commit
26f1e2c9e3
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "Log.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
@ -285,7 +286,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
ucontext_t* const ctx = (ucontext_t*)uct;
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr();
|
||||
//const bool is_writing = false; // TODO: get it correctly
|
||||
if (addr64 < 0x100000000ull)
|
||||
if (addr64 < 0x100000000ull && GetCurrentNamedThread())
|
||||
{
|
||||
const u32 addr = (u32)addr64;
|
||||
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers
|
||||
@ -384,7 +385,7 @@ NamedThreadBase* GetCurrentNamedThread()
|
||||
|
||||
void SetCurrentNamedThread(NamedThreadBase* value)
|
||||
{
|
||||
auto old_value = g_tls_this_thread;
|
||||
const auto old_value = g_tls_this_thread;
|
||||
|
||||
if (old_value == value)
|
||||
{
|
||||
@ -536,23 +537,63 @@ bool ThreadBase::TestDestroy() const
|
||||
return m_destroy;
|
||||
}
|
||||
|
||||
thread::thread(const std::string& name, std::function<void()> func) : m_name(name)
|
||||
thread_t::thread_t(const std::string& name, bool autojoin, std::function<void()> func)
|
||||
: m_name(name)
|
||||
, m_state(TS_NON_EXISTENT)
|
||||
, m_autojoin(autojoin)
|
||||
{
|
||||
start(func);
|
||||
}
|
||||
|
||||
thread::thread(const std::string& name) : m_name(name)
|
||||
thread_t::thread_t(const std::string& name, std::function<void()> func)
|
||||
: m_name(name)
|
||||
, m_state(TS_NON_EXISTENT)
|
||||
, m_autojoin(false)
|
||||
{
|
||||
start(func);
|
||||
}
|
||||
|
||||
thread_t::thread_t(const std::string& name)
|
||||
: m_name(name)
|
||||
, m_state(TS_NON_EXISTENT)
|
||||
, m_autojoin(false)
|
||||
{
|
||||
}
|
||||
|
||||
thread::thread()
|
||||
thread_t::thread_t()
|
||||
: m_state(TS_NON_EXISTENT)
|
||||
, m_autojoin(false)
|
||||
{
|
||||
}
|
||||
|
||||
void thread::start(std::function<void()> func)
|
||||
void thread_t::set_name(const std::string& name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
thread_t::~thread_t()
|
||||
{
|
||||
if (m_state == TS_JOINABLE)
|
||||
{
|
||||
if (m_autojoin)
|
||||
{
|
||||
m_thr.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_thr.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void thread_t::start(std::function<void()> func)
|
||||
{
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.join(); // forcefully join previously created thread
|
||||
}
|
||||
|
||||
std::string name = m_name;
|
||||
|
||||
m_thr = std::thread([func, name]()
|
||||
{
|
||||
SetCurrentThreadDebugName(name.c_str());
|
||||
@ -567,6 +608,11 @@ void thread::start(std::function<void()> func)
|
||||
SetCurrentNamedThread(&info);
|
||||
g_thread_count++;
|
||||
|
||||
if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " started");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
func();
|
||||
@ -580,6 +626,15 @@ void thread::start(std::function<void()> func)
|
||||
LOG_ERROR(GENERAL, "%s: %s", name.c_str(), e.c_str());
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " aborted");
|
||||
}
|
||||
else if (Ini.HLELogging.GetValue())
|
||||
{
|
||||
LOG_NOTICE(HLE, name + " ended");
|
||||
}
|
||||
|
||||
SetCurrentNamedThread(nullptr);
|
||||
g_thread_count--;
|
||||
|
||||
@ -587,21 +642,41 @@ void thread::start(std::function<void()> func)
|
||||
_set_se_translator(old_se_translator);
|
||||
#endif
|
||||
});
|
||||
|
||||
if (m_state.exchange(TS_JOINABLE) == TS_JOINABLE)
|
||||
{
|
||||
assert(!"thread_t::start() failed"); // probably started from another thread
|
||||
}
|
||||
}
|
||||
|
||||
void thread::detach()
|
||||
void thread_t::detach()
|
||||
{
|
||||
m_thr.detach();
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"thread_t::detach() failed"); // probably joined or detached
|
||||
}
|
||||
}
|
||||
|
||||
void thread::join()
|
||||
void thread_t::join()
|
||||
{
|
||||
m_thr.join();
|
||||
if (m_state.exchange(TS_NON_EXISTENT) == TS_JOINABLE)
|
||||
{
|
||||
m_thr.join();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!"thread_t::join() failed"); // probably joined or detached
|
||||
}
|
||||
}
|
||||
|
||||
bool thread::joinable() const
|
||||
bool thread_t::joinable() const
|
||||
{
|
||||
return m_thr.joinable();
|
||||
//return m_thr.joinable();
|
||||
return m_state == TS_JOINABLE;
|
||||
}
|
||||
|
||||
bool waiter_map_t::is_stopped(u64 signal_id)
|
||||
@ -665,7 +740,10 @@ void waiter_map_t::notify(u64 signal_id)
|
||||
}
|
||||
}
|
||||
|
||||
bool squeue_test_exit(const volatile bool* do_exit)
|
||||
const std::function<bool()> SQUEUE_ALWAYS_EXIT = [](){ return true; };
|
||||
const std::function<bool()> SQUEUE_NEVER_EXIT = [](){ return false; };
|
||||
|
||||
bool squeue_test_exit()
|
||||
{
|
||||
return Emu.IsStopped() || (do_exit && *do_exit);
|
||||
return Emu.IsStopped();
|
||||
}
|
||||
|
@ -54,18 +54,34 @@ public:
|
||||
virtual void Task() = 0;
|
||||
};
|
||||
|
||||
class thread
|
||||
class thread_t
|
||||
{
|
||||
enum thread_state_t
|
||||
{
|
||||
TS_NON_EXISTENT,
|
||||
TS_JOINABLE,
|
||||
};
|
||||
|
||||
std::atomic<thread_state_t> m_state;
|
||||
std::string m_name;
|
||||
std::thread m_thr;
|
||||
bool m_autojoin;
|
||||
|
||||
public:
|
||||
thread(const std::string& name, std::function<void()> func);
|
||||
thread(const std::string& name);
|
||||
thread();
|
||||
thread_t(const std::string& name, bool autojoin, std::function<void()> func);
|
||||
thread_t(const std::string& name, std::function<void()> func);
|
||||
thread_t(const std::string& name);
|
||||
thread_t();
|
||||
~thread_t();
|
||||
|
||||
thread_t(const thread_t& right) = delete;
|
||||
thread_t(thread_t&& right) = delete;
|
||||
|
||||
thread_t& operator =(const thread_t& right) = delete;
|
||||
thread_t& operator =(thread_t&& right) = delete;
|
||||
|
||||
public:
|
||||
void set_name(const std::string& name);
|
||||
void start(std::function<void()> func);
|
||||
void detach();
|
||||
void join();
|
||||
@ -148,7 +164,10 @@ public:
|
||||
void notify(u64 signal_id);
|
||||
};
|
||||
|
||||
bool squeue_test_exit(const volatile bool* do_exit);
|
||||
extern const std::function<bool()> SQUEUE_ALWAYS_EXIT;
|
||||
extern const std::function<bool()> SQUEUE_NEVER_EXIT;
|
||||
|
||||
bool squeue_test_exit();
|
||||
|
||||
template<typename T, u32 sq_size = 256>
|
||||
class squeue_t
|
||||
@ -199,7 +218,7 @@ public:
|
||||
return m_sync.read_relaxed().count == sq_size;
|
||||
}
|
||||
|
||||
bool push(const T& data, const volatile bool* do_exit = nullptr)
|
||||
bool push(const T& data, const std::function<bool()>& test_exit)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
@ -222,7 +241,7 @@ public:
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -247,14 +266,22 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_push(const T& data)
|
||||
bool push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
|
||||
return push(data, &no_wait);
|
||||
return push(data, [do_exit](){ return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
bool pop(T& data, const volatile bool* do_exit = nullptr)
|
||||
__forceinline bool push(const T& data)
|
||||
{
|
||||
return push(data, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
__forceinline bool try_push(const T& data)
|
||||
{
|
||||
return push(data, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
bool pop(T& data, const std::function<bool()>& test_exit)
|
||||
{
|
||||
u32 pos = 0;
|
||||
|
||||
@ -277,7 +304,7 @@ public:
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -307,14 +334,22 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_pop(T& data)
|
||||
bool pop(T& data, const volatile bool* do_exit)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
|
||||
return pop(data, &no_wait);
|
||||
return pop(data, [do_exit](){ return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos = 0, const volatile bool* do_exit = nullptr)
|
||||
__forceinline bool pop(T& data)
|
||||
{
|
||||
return pop(data, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
__forceinline bool try_pop(T& data)
|
||||
{
|
||||
return pop(data, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
bool peek(T& data, u32 start_pos, const std::function<bool()>& test_exit)
|
||||
{
|
||||
assert(start_pos < sq_size);
|
||||
u32 pos = 0;
|
||||
@ -332,13 +367,13 @@ public:
|
||||
{
|
||||
return SQSVR_LOCKED;
|
||||
}
|
||||
|
||||
|
||||
sync.pop_lock = 1;
|
||||
pos = sync.position + start_pos;
|
||||
return SQSVR_OK;
|
||||
}))
|
||||
{
|
||||
if (res == SQSVR_FAILED && squeue_test_exit(do_exit))
|
||||
if (res == SQSVR_FAILED && (test_exit() || squeue_test_exit()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -361,11 +396,19 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_peek(T& data, u32 start_pos = 0)
|
||||
bool peek(T& data, u32 start_pos, const volatile bool* do_exit)
|
||||
{
|
||||
static const volatile bool no_wait = true;
|
||||
return peek(data, start_pos, [do_exit](){ return do_exit && *do_exit; });
|
||||
}
|
||||
|
||||
return peek(data, start_pos, &no_wait);
|
||||
__forceinline bool peek(T& data, u32 start_pos = 0)
|
||||
{
|
||||
return peek(data, start_pos, SQUEUE_NEVER_EXIT);
|
||||
}
|
||||
|
||||
__forceinline bool try_peek(T& data, u32 start_pos = 0)
|
||||
{
|
||||
return peek(data, start_pos, SQUEUE_ALWAYS_EXIT);
|
||||
}
|
||||
|
||||
class squeue_data_t
|
||||
|
@ -26,7 +26,7 @@ namespace sce_libc_func
|
||||
});
|
||||
}
|
||||
|
||||
void printf(vm::psv::ptr<const char> fmt)
|
||||
void printf(vm::psv::ptr<const char> fmt) // va_args...
|
||||
{
|
||||
sceLibc.Error("printf(fmt=0x%x)", fmt);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include <unordered_map>
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "PSVFuncList.h"
|
||||
@ -7,29 +8,19 @@ std::vector<psv_func> g_psv_func_list;
|
||||
|
||||
void add_psv_func(psv_func& data)
|
||||
{
|
||||
// setup special functions (without NIDs)
|
||||
if (!g_psv_func_list.size())
|
||||
{
|
||||
psv_func unimplemented;
|
||||
unimplemented.nid = 0x00000000; // must not be a valid id
|
||||
unimplemented.name = "INVALID FUNCTION (0x0)";
|
||||
unimplemented.func.reset(new psv_func_detail::func_binder<u32>([]() -> u32
|
||||
{
|
||||
LOG_ERROR(HLE, "Unimplemented function executed");
|
||||
Emu.Pause();
|
||||
|
||||
return 0xffffffffu;
|
||||
}));
|
||||
unimplemented.nid = 0;
|
||||
unimplemented.name = "Special function (unimplemented stub)";
|
||||
unimplemented.func.reset(new psv_func_detail::func_binder<void, ARMv7Thread&>([](ARMv7Thread& CPU){ CPU.m_last_syscall = vm::psv::read32(CPU.PC + 4); throw "Unimplemented function executed"; }));
|
||||
g_psv_func_list.push_back(unimplemented);
|
||||
|
||||
psv_func hle_return;
|
||||
hle_return.nid = 0x00000001; // must not be a valid id
|
||||
hle_return.name = "INVALID FUNCTION (0x1)";
|
||||
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Thread&>([](ARMv7Thread& CPU)
|
||||
{
|
||||
CPU.FastStop();
|
||||
|
||||
return;
|
||||
}));
|
||||
hle_return.nid = 1;
|
||||
hle_return.name = "Special function (return from HLE)";
|
||||
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Thread&>([](ARMv7Thread& CPU){ CPU.FastStop(); }));
|
||||
g_psv_func_list.push_back(hle_return);
|
||||
}
|
||||
|
||||
@ -40,7 +31,7 @@ psv_func* get_psv_func_by_nid(u32 nid)
|
||||
{
|
||||
for (auto& f : g_psv_func_list)
|
||||
{
|
||||
if (f.nid == nid)
|
||||
if (f.nid == nid && &f - g_psv_func_list.data() >= 2 /* special functions count */)
|
||||
{
|
||||
return &f;
|
||||
}
|
||||
@ -61,8 +52,13 @@ u32 get_psv_func_index(psv_func* func)
|
||||
void execute_psv_func_by_index(ARMv7Thread& CPU, u32 index)
|
||||
{
|
||||
assert(index < g_psv_func_list.size());
|
||||
|
||||
auto old_last_syscall = CPU.m_last_syscall;
|
||||
CPU.m_last_syscall = g_psv_func_list[index].nid;
|
||||
|
||||
(*g_psv_func_list[index].func)(CPU);
|
||||
|
||||
CPU.m_last_syscall = old_last_syscall;
|
||||
}
|
||||
|
||||
extern psv_log_base sceLibc;
|
||||
|
@ -11,8 +11,6 @@ ALCenum g_last_alc_error = ALC_NO_ERROR;
|
||||
#define checkForAlError(sit) if((g_last_al_error = alGetError()) != AL_NO_ERROR) printAlError(g_last_al_error, sit)
|
||||
#define checkForAlcError(sit) if((g_last_alc_error = alcGetError(m_device)) != ALC_NO_ERROR) printAlcError(g_last_alc_error, sit)
|
||||
|
||||
static const ALenum g_audio_format = Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO_FLOAT32;
|
||||
|
||||
void printAlError(ALenum err, const char* situation)
|
||||
{
|
||||
if (err != AL_NO_ERROR)
|
||||
@ -102,7 +100,7 @@ void OpenALThread::Open(const void* src, int size)
|
||||
|
||||
for (uint i = 0; i<g_al_buffers_count; ++i)
|
||||
{
|
||||
alBufferData(m_buffers[i], g_audio_format, src, m_buffer_size, 48000);
|
||||
alBufferData(m_buffers[i], Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, src, m_buffer_size, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
}
|
||||
|
||||
@ -137,7 +135,7 @@ void OpenALThread::AddData(const void* src, int size)
|
||||
|
||||
int bsize = size < m_buffer_size ? size : m_buffer_size;
|
||||
|
||||
alBufferData(buffer, g_audio_format, bsrc, bsize, 48000);
|
||||
alBufferData(buffer, Ini.AudioConvertToU16.GetValue() ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32, bsrc, bsize, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
|
||||
alSourceQueueBuffers(m_source, 1, &buffer);
|
||||
|
@ -24,4 +24,4 @@ public:
|
||||
virtual void Close();
|
||||
virtual void Stop();
|
||||
virtual void AddData(const void* src, int size);
|
||||
};
|
||||
};
|
||||
|
@ -1,22 +1,32 @@
|
||||
#include "stdafx.h"
|
||||
#include "AudioDumper.h"
|
||||
|
||||
AudioDumper::AudioDumper(u8 ch) : m_header(ch)
|
||||
AudioDumper::AudioDumper() : m_header(0), m_init(false)
|
||||
{
|
||||
}
|
||||
|
||||
AudioDumper::~AudioDumper()
|
||||
{
|
||||
Finalize();
|
||||
}
|
||||
|
||||
bool AudioDumper::Init()
|
||||
bool AudioDumper::Init(u8 ch)
|
||||
{
|
||||
return m_output.Open("audio.wav", rFile::write);
|
||||
if ((m_init = m_output.Open("audio.wav", rFile::write)))
|
||||
{
|
||||
m_header = WAVHeader(ch);
|
||||
WriteHeader();
|
||||
}
|
||||
|
||||
return m_init;
|
||||
}
|
||||
|
||||
void AudioDumper::WriteHeader()
|
||||
{
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write file header
|
||||
if (m_init)
|
||||
{
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write file header
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||
@ -31,17 +41,27 @@ size_t AudioDumper::WriteData(const void* buffer, size_t size)
|
||||
{
|
||||
if (((u8*)buffer)[i + (size & ~7)]) do_save = true;
|
||||
}
|
||||
if (!do_save) return size; // ignore empty data
|
||||
|
||||
if (m_init && do_save)
|
||||
#else
|
||||
if (m_init)
|
||||
#endif
|
||||
size_t ret = m_output.Write(buffer, size);
|
||||
m_header.Size += (u32)ret;
|
||||
m_header.RIFF.Size += (u32)ret;
|
||||
return ret;
|
||||
{
|
||||
size_t ret = m_output.Write(buffer, size);
|
||||
m_header.Size += (u32)ret;
|
||||
m_header.RIFF.Size += (u32)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void AudioDumper::Finalize()
|
||||
{
|
||||
m_output.Seek(0);
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write fixed file header
|
||||
m_output.Close();
|
||||
if (m_init)
|
||||
{
|
||||
m_output.Seek(0);
|
||||
m_output.Write(&m_header, sizeof(m_header)); // write fixed file header
|
||||
m_output.Close();
|
||||
}
|
||||
}
|
@ -55,15 +55,16 @@ struct WAVHeader
|
||||
|
||||
class AudioDumper
|
||||
{
|
||||
private:
|
||||
WAVHeader m_header;
|
||||
rFile m_output;
|
||||
bool m_init;
|
||||
|
||||
public:
|
||||
AudioDumper(u8 ch);
|
||||
AudioDumper();
|
||||
~AudioDumper();
|
||||
|
||||
bool Init();
|
||||
public:
|
||||
bool Init(u8 ch);
|
||||
void WriteHeader();
|
||||
size_t WriteData(const void* buffer, size_t size);
|
||||
void Finalize();
|
||||
|
@ -21,9 +21,9 @@ struct AudioInfo
|
||||
void Init()
|
||||
{
|
||||
mode.type = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
mode.channel = CELL_AUDIO_OUT_CHNUM_2;
|
||||
mode.channel = CELL_AUDIO_OUT_CHNUM_8;
|
||||
mode.fs = CELL_AUDIO_OUT_FS_48KHZ;
|
||||
mode.layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_2CH;
|
||||
mode.layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_8CH_LREClrxy;
|
||||
mode.encoder = CELL_AUDIO_OUT_CODING_TYPE_LPCM;
|
||||
mode.downMixer = CELL_AUDIO_OUT_DOWNMIXER_NONE;
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ public:
|
||||
virtual void Close() {}
|
||||
virtual void Stop() {}
|
||||
virtual void AddData(const void* src, int size) {}
|
||||
};
|
||||
};
|
||||
|
@ -8,13 +8,14 @@
|
||||
|
||||
XAudio2Thread::~XAudio2Thread()
|
||||
{
|
||||
Quit();
|
||||
if (m_source_voice) Quit();
|
||||
}
|
||||
|
||||
void XAudio2Thread::Init()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
#if (_WIN32_WINNT < 0x0602)
|
||||
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@ -22,6 +23,7 @@ void XAudio2Thread::Init()
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
hr = XAudio2Create(&m_xaudio2_instance, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
||||
if (FAILED(hr))
|
||||
@ -50,6 +52,10 @@ void XAudio2Thread::Quit()
|
||||
m_xaudio2_instance->StopEngine();
|
||||
m_xaudio2_instance->Release();
|
||||
m_xaudio2_instance = nullptr;
|
||||
|
||||
#if (_WIN32_WINNT < 0x0602)
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
void XAudio2Thread::Play()
|
||||
@ -87,13 +93,16 @@ void XAudio2Thread::Open(const void* src, int size)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
WORD sample_size = Ini.AudioConvertToU16.GetValue() ? sizeof(u16) : sizeof(float);
|
||||
WORD channels = 8;
|
||||
|
||||
WAVEFORMATEX waveformatex;
|
||||
waveformatex.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
waveformatex.nChannels = 2;
|
||||
waveformatex.wFormatTag = Ini.AudioConvertToU16.GetValue() ? WAVE_FORMAT_PCM : WAVE_FORMAT_IEEE_FLOAT;
|
||||
waveformatex.nChannels = channels;
|
||||
waveformatex.nSamplesPerSec = 48000;
|
||||
waveformatex.nAvgBytesPerSec = 48000 * 2 * sizeof(float);
|
||||
waveformatex.nBlockAlign = 2 * sizeof(float);
|
||||
waveformatex.wBitsPerSample = 32;
|
||||
waveformatex.nAvgBytesPerSec = 48000 * (DWORD)channels * (DWORD)sample_size;
|
||||
waveformatex.nBlockAlign = channels * sample_size;
|
||||
waveformatex.wBitsPerSample = sample_size * 8;
|
||||
waveformatex.cbSize = 0;
|
||||
|
||||
hr = m_xaudio2_instance->CreateSourceVoice(&m_source_voice, &waveformatex, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
@ -129,4 +138,4 @@ void XAudio2Thread::AddData(const void* src, int size)
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "stdafx.h"
|
||||
#include "rpcs3/Ini.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/DbgCommand.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
||||
#include "CPUDecoder.h"
|
||||
#include "CPUThread.h"
|
||||
@ -256,6 +257,70 @@ void CPUThread::ExecOnce()
|
||||
|
||||
void CPUThread::Task()
|
||||
{
|
||||
auto get_syscall_name = [this](u64 syscall) -> std::string
|
||||
{
|
||||
switch (GetType())
|
||||
{
|
||||
case CPU_THREAD_ARMv7:
|
||||
{
|
||||
if ((u32)syscall == syscall)
|
||||
{
|
||||
if (syscall)
|
||||
{
|
||||
if (auto func = get_psv_func_by_nid((u32)syscall))
|
||||
{
|
||||
return func->name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return{};
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
|
||||
case CPU_THREAD_PPU:
|
||||
{
|
||||
if ((u32)syscall == syscall)
|
||||
{
|
||||
if (syscall)
|
||||
{
|
||||
if (syscall < 1024)
|
||||
{
|
||||
// TODO:
|
||||
//return SysCalls::GetSyscallName((u32)syscall);
|
||||
return "unknown syscall";
|
||||
}
|
||||
else
|
||||
{
|
||||
return SysCalls::GetHLEFuncName((u32)syscall);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return{};
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
|
||||
case CPU_THREAD_SPU:
|
||||
case CPU_THREAD_RAW_SPU:
|
||||
default:
|
||||
{
|
||||
if (!syscall)
|
||||
{
|
||||
return{};
|
||||
}
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s enter", CPUThread::GetFName().c_str());
|
||||
|
||||
const std::vector<u64>& bp = Emu.GetBreakPoints();
|
||||
@ -310,13 +375,13 @@ void CPUThread::Task()
|
||||
}
|
||||
catch (const std::string& e)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Exception: %s (is_alive=%d, m_last_syscall=0x%llx (%s))", e, IsAlive(), m_last_syscall, SysCalls::GetHLEFuncName((u32)m_last_syscall));
|
||||
LOG_ERROR(GENERAL, "Exception: %s (is_alive=%d, m_last_syscall=0x%llx (%s))", e, IsAlive(), m_last_syscall, get_syscall_name(m_last_syscall));
|
||||
LOG_NOTICE(GENERAL, RegsToString());
|
||||
Emu.Pause();
|
||||
}
|
||||
catch (const char* e)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Exception: %s (is_alive=%d, m_last_syscall=0x%llx (%s))", e, IsAlive(), m_last_syscall, SysCalls::GetHLEFuncName((u32)m_last_syscall));
|
||||
LOG_ERROR(GENERAL, "Exception: %s (is_alive=%d, m_last_syscall=0x%llx (%s))", e, IsAlive(), m_last_syscall, get_syscall_name(m_last_syscall));
|
||||
LOG_NOTICE(GENERAL, RegsToString());
|
||||
Emu.Pause();
|
||||
}
|
||||
|
@ -841,9 +841,9 @@ public:
|
||||
template<typename T, size_t size = sizeof(T)>
|
||||
struct cast_ppu_gpr
|
||||
{
|
||||
static_assert(sizeof(T) <= 8, "Type for cast_ppu_gpr is invalid (too big)");
|
||||
static_assert(sizeof(T) <= 8, "Invalid type for cast_ppu_gpr");
|
||||
|
||||
static u64 func(const T& value)
|
||||
__forceinline static u64 to_gpr(const T& value)
|
||||
{
|
||||
u64 result = 0;
|
||||
(T&)result = value;
|
||||
@ -854,7 +854,7 @@ struct cast_ppu_gpr
|
||||
template<typename T>
|
||||
struct cast_ppu_gpr<T, 1>
|
||||
{
|
||||
static u64 func(const T& value)
|
||||
__forceinline static u64 to_gpr(const T& value)
|
||||
{
|
||||
return (u8&)value;
|
||||
}
|
||||
@ -863,7 +863,7 @@ struct cast_ppu_gpr<T, 1>
|
||||
template<typename T>
|
||||
struct cast_ppu_gpr<T, 2>
|
||||
{
|
||||
static u64 func(const T& value)
|
||||
__forceinline static u64 to_gpr(const T& value)
|
||||
{
|
||||
return (u16&)value;
|
||||
}
|
||||
@ -872,7 +872,7 @@ struct cast_ppu_gpr<T, 2>
|
||||
template<typename T>
|
||||
struct cast_ppu_gpr<T, 4>
|
||||
{
|
||||
static u64 func(const T& value)
|
||||
__forceinline static u64 to_gpr(const T& value)
|
||||
{
|
||||
return (u32&)value;
|
||||
}
|
||||
@ -881,7 +881,7 @@ struct cast_ppu_gpr<T, 4>
|
||||
template<typename T>
|
||||
struct cast_ppu_gpr<T, 8>
|
||||
{
|
||||
static u64 func(const T& value)
|
||||
__forceinline static u64 to_gpr(const T& value)
|
||||
{
|
||||
return (u64&)value;
|
||||
}
|
||||
@ -890,7 +890,7 @@ struct cast_ppu_gpr<T, 8>
|
||||
template<>
|
||||
struct cast_ppu_gpr<s8, 1>
|
||||
{
|
||||
static u64 func(const s8& value)
|
||||
__forceinline static u64 to_gpr(const s8& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
@ -899,7 +899,7 @@ struct cast_ppu_gpr<s8, 1>
|
||||
template<>
|
||||
struct cast_ppu_gpr<s16, 2>
|
||||
{
|
||||
static u64 func(const s16& value)
|
||||
__forceinline static u64 to_gpr(const s16& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
@ -908,7 +908,7 @@ struct cast_ppu_gpr<s16, 2>
|
||||
template<>
|
||||
struct cast_ppu_gpr<s32, 4>
|
||||
{
|
||||
static u64 func(const s32& value)
|
||||
__forceinline static u64 to_gpr(const s32& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
@ -917,8 +917,14 @@ struct cast_ppu_gpr<s32, 4>
|
||||
template<>
|
||||
struct cast_ppu_gpr<s64, 8>
|
||||
{
|
||||
static u64 func(const s64& value)
|
||||
__forceinline static u64 to_gpr(const s64& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
__forceinline static u64 cast_to_ppu_gpr(const T& value)
|
||||
{
|
||||
return cast_ppu_gpr<T>::to_gpr(value);
|
||||
}
|
||||
|
@ -2348,22 +2348,15 @@ void RSXThread::Task()
|
||||
OnInitThread();
|
||||
|
||||
m_last_flip_time = get_system_time() - 1000000;
|
||||
volatile bool is_vblank_stopped = false;
|
||||
|
||||
thread vblank("VBlank thread", [&]()
|
||||
thread_t vblank("VBlank thread", true /* autojoin */, [this]()
|
||||
{
|
||||
const u64 start_time = get_system_time();
|
||||
|
||||
m_vblank_count = 0;
|
||||
|
||||
while (!TestDestroy())
|
||||
while (!TestDestroy() && !Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(RSX, "VBlank thread aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_system_time() - start_time > m_vblank_count * 1000000 / 60)
|
||||
{
|
||||
m_vblank_count++;
|
||||
@ -2380,17 +2373,14 @@ void RSXThread::Task()
|
||||
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
is_vblank_stopped = true;
|
||||
});
|
||||
vblank.detach();
|
||||
|
||||
while (!TestDestroy()) try
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(RSX, "RSX thread aborted");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(m_cs_main);
|
||||
|
||||
@ -2409,7 +2399,7 @@ void RSXThread::Task()
|
||||
m_sem_flush.post_and_wait();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2476,24 +2466,17 @@ void RSXThread::Task()
|
||||
value += (count + 1) * 4;
|
||||
});
|
||||
}
|
||||
|
||||
catch (const std::string& e)
|
||||
{
|
||||
LOG_ERROR(RSX, "Exception: %s", e.c_str());
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
catch (const char* e)
|
||||
{
|
||||
LOG_ERROR(RSX, "Exception: %s", e);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
while (!is_vblank_stopped)
|
||||
{
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds(1)); // hack
|
||||
}
|
||||
|
||||
LOG_NOTICE(RSX, "RSX thread ended");
|
||||
|
||||
OnExitThread();
|
||||
|
@ -26,7 +26,7 @@ namespace cb_detail
|
||||
|
||||
__forceinline static void set_value(PPUThread& CPU, const T& arg)
|
||||
{
|
||||
CPU.GPR[g_count + 2] = cast_ppu_gpr<T>::func(arg);
|
||||
CPU.GPR[g_count + 2] = cast_to_ppu_gpr<T>(arg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -63,7 +63,7 @@ namespace cb_detail
|
||||
{
|
||||
const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE;
|
||||
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
|
||||
vm::write64(CPU.GPR[1] + stack_pos, cast_ppu_gpr<T>::func(arg));
|
||||
vm::write64(CPU.GPR[1] + stack_pos, cast_to_ppu_gpr<T>(arg));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -82,7 +82,7 @@ void CallbackManager::Init()
|
||||
static_cast<PPUThread*>(m_cb_thread)->DoRun();
|
||||
}
|
||||
|
||||
thread cb_async_thread("CallbackManager::Async() thread", [this]()
|
||||
thread_t cb_async_thread("CallbackManager thread", [this]()
|
||||
{
|
||||
SetCurrentNamedThread(m_cb_thread);
|
||||
|
||||
@ -108,8 +108,6 @@ void CallbackManager::Init()
|
||||
m_cb_thread->WaitForAnySignal();
|
||||
}
|
||||
});
|
||||
|
||||
cb_async_thread.detach();
|
||||
}
|
||||
|
||||
void CallbackManager::Clear()
|
||||
@ -119,3 +117,40 @@ void CallbackManager::Clear()
|
||||
m_cb_list.clear();
|
||||
m_async_list.clear();
|
||||
}
|
||||
|
||||
u64 CallbackManager::AddPauseCallback(const 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,21 +3,62 @@
|
||||
class CPUThread;
|
||||
class PPUThread;
|
||||
|
||||
typedef void(PauseResumeCB)(bool is_paused);
|
||||
|
||||
class CallbackManager
|
||||
{
|
||||
std::vector<std::function<s32(CPUThread& CPU)>> m_cb_list;
|
||||
std::vector<std::function<void(CPUThread& CPU)>> m_async_list;
|
||||
CPUThread* m_cb_thread;
|
||||
std::mutex m_mutex;
|
||||
std::vector<std::function<s32(CPUThread&)>> m_cb_list;
|
||||
std::vector<std::function<void(CPUThread&)>> m_async_list;
|
||||
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(const std::function<s32(PPUThread& PPU)>& func); // register callback (called in Check() method)
|
||||
void Register(const std::function<s32(PPUThread& CPU)>& func); // register callback (called in Check() method)
|
||||
|
||||
void Async(const std::function<void(PPUThread& PPU)>& func); // register callback for callback thread (called immediately)
|
||||
void Async(const std::function<void(PPUThread& CPU)>& func); // register callback for callback thread (called immediately)
|
||||
|
||||
bool Check(CPUThread& CPU, s32& result); // call one callback registered by Register() method
|
||||
|
||||
void Init();
|
||||
|
||||
void Clear();
|
||||
|
||||
u64 AddPauseCallback(const 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;
|
||||
|
||||
public:
|
||||
PauseCallbackRegisterer(CallbackManager& cb_manager, const std::function<PauseResumeCB>& func)
|
||||
: cb_manager(cb_manager)
|
||||
, cb_tag(cb_manager.AddPauseCallback(func))
|
||||
{
|
||||
}
|
||||
|
||||
PauseCallbackRegisterer() = delete;
|
||||
PauseCallbackRegisterer(const PauseCallbackRegisterer& right) = delete;
|
||||
PauseCallbackRegisterer(PauseCallbackRegisterer&& right) = delete;
|
||||
|
||||
~PauseCallbackRegisterer()
|
||||
{
|
||||
cb_manager.RemovePauseCallback(cb_tag);
|
||||
}
|
||||
|
||||
PauseCallbackRegisterer& operator =(const PauseCallbackRegisterer& right) = delete;
|
||||
PauseCallbackRegisterer& operator =(PauseCallbackRegisterer&& right) = delete;
|
||||
|
||||
};
|
||||
|
@ -224,7 +224,7 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
adec.id = adec_id;
|
||||
|
||||
adec.adecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback");
|
||||
adec.adecCb->SetName(fmt::format("AudioDecoder[%d] Callback", adec_id));
|
||||
adec.adecCb->SetEntry(0);
|
||||
adec.adecCb->SetPrio(1001);
|
||||
adec.adecCb->SetStackSize(0x10000);
|
||||
@ -232,11 +232,9 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
adec.adecCb->InitRegs();
|
||||
adec.adecCb->DoRun();
|
||||
|
||||
thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [adec_ptr, sptr]()
|
||||
thread_t t(fmt::format("AudioDecoder[%d] Thread", adec_id), [adec_ptr, sptr]()
|
||||
{
|
||||
AudioDecoder& adec = *adec_ptr;
|
||||
cellAdec->Notice("Audio Decoder thread started");
|
||||
|
||||
AdecTask& task = adec.task;
|
||||
|
||||
while (true)
|
||||
@ -471,18 +469,14 @@ u32 adecOpen(AudioDecoder* adec_ptr)
|
||||
|
||||
default:
|
||||
{
|
||||
ADEC_ERROR("Audio Decoder thread error: unknown task(%d)", task.type);
|
||||
ADEC_ERROR("AudioDecoder thread error: unknown task(%d)", task.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adec.is_finished = true;
|
||||
if (adec.is_closed) cellAdec->Notice("Audio Decoder thread ended");
|
||||
if (Emu.IsStopped()) cellAdec->Warning("Audio Decoder thread aborted");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return adec_id;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -72,51 +72,76 @@ struct CellAudioPortConfig
|
||||
be_t<u32> portAddr;
|
||||
};
|
||||
|
||||
enum : u32
|
||||
{
|
||||
BUFFER_NUM = 32,
|
||||
BUFFER_SIZE = 256,
|
||||
AUDIO_PORT_COUNT = 8,
|
||||
AUDIO_PORT_OFFSET = 256 * 1024,
|
||||
AUDIO_SAMPLES = CELL_AUDIO_BLOCK_SAMPLES,
|
||||
};
|
||||
|
||||
enum AudioState : u32
|
||||
{
|
||||
AUDIO_STATE_NOT_INITIALIZED,
|
||||
AUDIO_STATE_INITIALIZED,
|
||||
AUDIO_STATE_FINALIZED,
|
||||
};
|
||||
|
||||
enum AudioPortState : u32
|
||||
{
|
||||
AUDIO_PORT_STATE_CLOSED,
|
||||
AUDIO_PORT_STATE_OPENED,
|
||||
AUDIO_PORT_STATE_STARTED,
|
||||
};
|
||||
|
||||
struct AudioPortConfig
|
||||
{
|
||||
bool m_is_audio_port_opened;
|
||||
bool m_is_audio_port_started;
|
||||
u8 channel;
|
||||
u8 block;
|
||||
float level;
|
||||
std::mutex mutex;
|
||||
atomic_le_t<AudioPortState> state;
|
||||
|
||||
u32 channel;
|
||||
u32 block;
|
||||
u64 attr;
|
||||
u64 tag;
|
||||
u64 counter; // copy of global counter
|
||||
u32 addr;
|
||||
u32 read_index_addr;
|
||||
u32 size;
|
||||
float level;
|
||||
float level_set;
|
||||
float level_inc;
|
||||
};
|
||||
|
||||
struct AudioConfig //custom structure
|
||||
{
|
||||
enum
|
||||
{
|
||||
AUDIO_PORT_COUNT = 8,
|
||||
};
|
||||
AudioPortConfig m_ports[AUDIO_PORT_COUNT];
|
||||
u32 m_buffer; // 1 MB memory for audio ports
|
||||
u32 m_indexes; // current block indexes and other info
|
||||
bool m_is_audio_initialized;
|
||||
bool m_is_audio_finalized;
|
||||
u32 m_port_in_use;
|
||||
std::mutex mutex;
|
||||
atomic_le_t<AudioState> state;
|
||||
thread_t audio_thread;
|
||||
|
||||
AudioPortConfig ports[AUDIO_PORT_COUNT];
|
||||
u32 buffer; // 1 MB memory for audio ports
|
||||
u32 indexes; // current block indexes and other info
|
||||
u64 counter;
|
||||
u64 start_time;
|
||||
std::vector<u64> m_keys;
|
||||
std::vector<u64> keys;
|
||||
|
||||
AudioConfig()
|
||||
: m_is_audio_initialized(false)
|
||||
, m_is_audio_finalized(false)
|
||||
, m_port_in_use(0)
|
||||
, counter(0)
|
||||
AudioConfig() : audio_thread("Audio Thread")
|
||||
{
|
||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
u32 open_port()
|
||||
{
|
||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||
m_port_in_use = 0;
|
||||
for (u32 i = 0; i < AUDIO_PORT_COUNT; i++)
|
||||
{
|
||||
if (ports[i].state.compare_and_swap_test(AUDIO_PORT_STATE_CLOSED, AUDIO_PORT_STATE_OPENED))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return ~0;
|
||||
}
|
||||
};
|
||||
|
||||
extern AudioConfig m_config;
|
||||
extern AudioConfig g_audio;
|
@ -306,7 +306,7 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
dmux.id = dmux_id;
|
||||
|
||||
dmux.dmuxCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback");
|
||||
dmux.dmuxCb->SetName(fmt::format("Demuxer[%d] Callback", dmux_id));
|
||||
dmux.dmuxCb->SetEntry(0);
|
||||
dmux.dmuxCb->SetPrio(1001);
|
||||
dmux.dmuxCb->SetStackSize(0x10000);
|
||||
@ -314,10 +314,9 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
dmux.dmuxCb->InitRegs();
|
||||
dmux.dmuxCb->DoRun();
|
||||
|
||||
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [dmux_ptr, sptr]()
|
||||
thread_t t(fmt::format("Demuxer[%d] Thread", dmux_id), [dmux_ptr, sptr]()
|
||||
{
|
||||
Demuxer& dmux = *dmux_ptr;
|
||||
cellDmux->Notice("Demuxer thread started (mem=0x%x, size=0x%x, cb_addr=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc.addr(), dmux.cbArg);
|
||||
|
||||
DemuxerTask task;
|
||||
DemuxerStream stream = {};
|
||||
@ -760,12 +759,8 @@ u32 dmuxOpen(Demuxer* dmux_ptr)
|
||||
}
|
||||
|
||||
dmux.is_finished = true;
|
||||
if (Emu.IsStopped()) cellDmux->Warning("Demuxer thread aborted");
|
||||
if (dmux.is_closed) cellDmux->Notice("Demuxer thread ended");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return dmux_id;
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
||||
|
||||
std::string msg = msgString.get_ptr();
|
||||
|
||||
thread t("MsgDialog thread", [type, msg, callback, userData, extParam]()
|
||||
thread_t t("MsgDialog Thread", [type, msg, callback, userData, extParam]()
|
||||
{
|
||||
switch (type & CELL_MSGDIALOG_TYPE_SE_TYPE)
|
||||
{
|
||||
@ -186,7 +186,6 @@ s32 cellMsgDialogOpen2(u32 type, vm::ptr<const char> msgString, vm::ptr<CellMsgD
|
||||
g_msg_dialog_state = msgDialogNone;
|
||||
});
|
||||
});
|
||||
t.detach();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ int cellAudioOutGetSoundAvailability(u32 audioOut, u32 type, u32 fs, u32 option)
|
||||
|
||||
option = 0;
|
||||
|
||||
int available = 2; // should be at least 2
|
||||
int available = 8; // should be at least 2
|
||||
|
||||
switch(fs)
|
||||
{
|
||||
@ -431,7 +431,7 @@ int cellAudioOutGetSoundAvailability2(u32 audioOut, u32 type, u32 fs, u32 ch, u3
|
||||
|
||||
option = 0;
|
||||
|
||||
int available = 2; // should be at least 2
|
||||
int available = 8; // should be at least 2
|
||||
|
||||
switch(fs)
|
||||
{
|
||||
@ -578,9 +578,9 @@ int cellAudioOutGetDeviceInfo(u32 audioOut, u32 deviceIndex, vm::ptr<CellAudioOu
|
||||
info->state = CELL_AUDIO_OUT_DEVICE_STATE_AVAILABLE;
|
||||
info->latency = 1000;
|
||||
info->availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
|
||||
info->availableModes[0].channel = CELL_AUDIO_OUT_CHNUM_2;
|
||||
info->availableModes[0].channel = CELL_AUDIO_OUT_CHNUM_8;
|
||||
info->availableModes[0].fs = CELL_AUDIO_OUT_FS_48KHZ;
|
||||
info->availableModes[0].layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_2CH;
|
||||
info->availableModes[0].layout = CELL_AUDIO_OUT_SPEAKER_LAYOUT_8CH_LREClrxy;
|
||||
|
||||
return CELL_AUDIO_OUT_SUCCEEDED;
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
vdec.id = vdec_id;
|
||||
|
||||
vdec.vdecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");
|
||||
vdec.vdecCb->SetName(fmt::format("VideoDecoder[%d] Callback", vdec_id));
|
||||
vdec.vdecCb->SetEntry(0);
|
||||
vdec.vdecCb->SetPrio(1001);
|
||||
vdec.vdecCb->SetStackSize(0x10000);
|
||||
@ -222,11 +222,9 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
vdec.vdecCb->InitRegs();
|
||||
vdec.vdecCb->DoRun();
|
||||
|
||||
thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [vdec_ptr, sptr]()
|
||||
thread_t t(fmt::format("VideoDecoder[%d] Thread", vdec_id), [vdec_ptr, sptr]()
|
||||
{
|
||||
VideoDecoder& vdec = *vdec_ptr;
|
||||
cellVdec->Notice("Video Decoder thread started");
|
||||
|
||||
VdecTask& task = vdec.task;
|
||||
|
||||
while (true)
|
||||
@ -431,7 +429,15 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
{
|
||||
if (vdec.last_pts == -1)
|
||||
{
|
||||
vdec.last_pts = 0x8000; //av_frame_get_best_effort_timestamp(frame.data);
|
||||
u64 ts = av_frame_get_best_effort_timestamp(frame.data);
|
||||
if (ts != AV_NOPTS_VALUE)
|
||||
{
|
||||
vdec.last_pts = ts;
|
||||
}
|
||||
else
|
||||
{
|
||||
vdec.last_pts = 0;
|
||||
}
|
||||
}
|
||||
else switch (vdec.frc_set)
|
||||
{
|
||||
@ -539,18 +545,14 @@ u32 vdecOpen(VideoDecoder* vdec_ptr)
|
||||
|
||||
default:
|
||||
{
|
||||
VDEC_ERROR("Video Decoder thread error: unknown task(%d)", task.type);
|
||||
VDEC_ERROR("VideoDecoder thread error: unknown task(%d)", task.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdec.is_finished = true;
|
||||
if (Emu.IsStopped()) cellVdec->Warning("Video Decoder thread aborted");
|
||||
if (vdec.is_closed) cellVdec->Notice("Video Decoder thread ended");
|
||||
});
|
||||
|
||||
t.detach();
|
||||
|
||||
return vdec_id;
|
||||
}
|
||||
|
||||
|
@ -5,14 +5,12 @@
|
||||
#include "Emu/SysCalls/CB_FUNC.h"
|
||||
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
#include "Emu/Audio/cellAudio.h"
|
||||
#include "cellAudio.h"
|
||||
#include "libmixer.h"
|
||||
|
||||
Module *libmixer = nullptr;
|
||||
|
||||
CellSurMixerConfig surMixer;
|
||||
|
||||
#define SUR_PORT (7)
|
||||
SurMixerConfig g_surmx;
|
||||
vm::ptr<CellSurMixerNotifyCallbackFunction> surMixerCb;
|
||||
vm::ptr<void> surMixerCbArg;
|
||||
std::mutex mixer_mutex;
|
||||
@ -31,13 +29,13 @@ int cellAANAddData(u32 aan_handle, u32 aan_port, u32 offset, vm::ptr<float> addr
|
||||
switch (type)
|
||||
{
|
||||
case CELL_SURMIXER_CHSTRIP_TYPE1A:
|
||||
if (port >= surMixer.chStrips1) type = 0; break;
|
||||
if (port >= g_surmx.ch_strips_1) type = 0; break;
|
||||
case CELL_SURMIXER_CHSTRIP_TYPE2A:
|
||||
if (port >= surMixer.chStrips2) type = 0; break;
|
||||
if (port >= g_surmx.ch_strips_2) type = 0; break;
|
||||
case CELL_SURMIXER_CHSTRIP_TYPE6A:
|
||||
if (port >= surMixer.chStrips6) type = 0; break;
|
||||
if (port >= g_surmx.ch_strips_6) type = 0; break;
|
||||
case CELL_SURMIXER_CHSTRIP_TYPE8A:
|
||||
if (port >= surMixer.chStrips8) type = 0; break;
|
||||
if (port >= g_surmx.ch_strips_8) type = 0; break;
|
||||
default:
|
||||
type = 0; break;
|
||||
}
|
||||
@ -296,35 +294,37 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
{
|
||||
libmixer->Warning("cellSurMixerCreate(config_addr=0x%x)", config.addr());
|
||||
|
||||
surMixer = *config;
|
||||
g_surmx.audio_port = g_audio.open_port();
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
if (!~g_surmx.audio_port)
|
||||
{
|
||||
return CELL_LIBMIXER_ERROR_FULL;
|
||||
}
|
||||
|
||||
g_surmx.priority = config->priority;
|
||||
g_surmx.ch_strips_1 = config->chStrips1;
|
||||
g_surmx.ch_strips_2 = config->chStrips2;
|
||||
g_surmx.ch_strips_6 = config->chStrips6;
|
||||
g_surmx.ch_strips_8 = config->chStrips8;
|
||||
|
||||
AudioPortConfig& port = g_audio.ports[g_surmx.audio_port];
|
||||
|
||||
port.channel = 8;
|
||||
port.block = 16;
|
||||
port.attr = 0;
|
||||
port.level = 1.0f;
|
||||
port.tag = 0;
|
||||
|
||||
libmixer->Warning("*** audio port opened(default)");
|
||||
|
||||
port.m_is_audio_port_opened = true;
|
||||
port.tag = 0;
|
||||
m_config.m_port_in_use++;
|
||||
|
||||
libmixer->Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)",
|
||||
(u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8);
|
||||
|
||||
mixcount = 0;
|
||||
surMixerCb.set(0);
|
||||
|
||||
thread t("Surmixer Thread", []()
|
||||
libmixer->Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)", config->chStrips1, config->chStrips2, config->chStrips6, config->chStrips8);
|
||||
|
||||
thread_t t("Surmixer Thread", []()
|
||||
{
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
AudioPortConfig& port = g_audio.ports[g_surmx.audio_port];
|
||||
|
||||
PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
cb_thread.SetName("Surmixer Callback Thread");
|
||||
@ -335,21 +335,15 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
cb_thread.InitRegs();
|
||||
cb_thread.DoRun();
|
||||
|
||||
while (port.m_is_audio_port_opened)
|
||||
while (port.state.read_relaxed() != AUDIO_PORT_STATE_CLOSED && !Emu.IsStopped())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
libmixer->Warning("Surmixer aborted");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port.m_is_audio_port_started)
|
||||
if (port.state.read_relaxed() == AUDIO_PORT_STATE_STARTED)
|
||||
{
|
||||
//u64 stamp0 = get_system_time();
|
||||
|
||||
@ -440,7 +434,7 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
|
||||
//u64 stamp2 = get_system_time();
|
||||
|
||||
auto buf = vm::get_ptr<be_t<float>>(m_config.m_buffer + (128 * 1024 * SUR_PORT) + (mixcount % port.block) * port.channel * 256 * sizeof(float));
|
||||
auto buf = vm::get_ptr<be_t<float>>(port.addr + (mixcount % port.block) * port.channel * AUDIO_SAMPLES * sizeof(float));
|
||||
|
||||
for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
|
||||
{
|
||||
@ -464,7 +458,6 @@ int cellSurMixerCreate(vm::ptr<const CellSurMixerConfig> config)
|
||||
Emu.GetCPU().RemoveThread(cb_thread.GetId());
|
||||
surMixerCb.set(0);
|
||||
});
|
||||
t.detach();
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -515,13 +508,13 @@ int cellSurMixerStart()
|
||||
{
|
||||
libmixer->Warning("cellSurMixerStart()");
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
if (g_surmx.audio_port >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
port.m_is_audio_port_started = true;
|
||||
return CELL_LIBMIXER_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
|
||||
g_audio.ports[g_surmx.audio_port].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_STARTED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -535,19 +528,17 @@ int cellSurMixerFinalize()
|
||||
{
|
||||
libmixer->Warning("cellSurMixerFinalize()");
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
if (g_surmx.audio_port >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
port.m_is_audio_port_started = false;
|
||||
port.m_is_audio_port_opened = false;
|
||||
m_config.m_port_in_use--;
|
||||
return CELL_LIBMIXER_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
g_audio.ports[g_surmx.audio_port].state.compare_and_swap(AUDIO_PORT_STATE_OPENED, AUDIO_PORT_STATE_CLOSED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples)
|
||||
int cellSurMixerSurBusAddData(u32 busNo, u32 offset, vm::ptr<float> addr, u32 samples)
|
||||
{
|
||||
if (busNo < 8 && samples == 256 && offset == 0)
|
||||
{
|
||||
@ -564,8 +555,7 @@ int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples)
|
||||
for (u32 i = 0; i < samples; i++)
|
||||
{
|
||||
// reverse byte order and mix
|
||||
u32 v = vm::read32(addr + i * sizeof(float));
|
||||
mixdata[i*8+busNo] += (float&)v;
|
||||
mixdata[i * 8 + busNo] += addr[i];
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -581,13 +571,13 @@ int cellSurMixerPause(u32 type)
|
||||
{
|
||||
libmixer->Warning("cellSurMixerPause(type=%d)", type);
|
||||
|
||||
AudioPortConfig& port = m_config.m_ports[SUR_PORT];
|
||||
|
||||
if (port.m_is_audio_port_opened)
|
||||
if (g_surmx.audio_port >= AUDIO_PORT_COUNT)
|
||||
{
|
||||
port.m_is_audio_port_started = false;
|
||||
return CELL_LIBMIXER_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
g_audio.ports[g_surmx.audio_port].state.compare_and_swap(AUDIO_PORT_STATE_STARTED, AUDIO_PORT_STATE_OPENED);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -603,7 +593,7 @@ int cellSurMixerGetTimestamp(u64 tag, vm::ptr<u64> stamp)
|
||||
{
|
||||
libmixer->Log("cellSurMixerGetTimestamp(tag=0x%llx, stamp_addr=0x%x)", tag, stamp.addr());
|
||||
|
||||
*stamp = m_config.start_time + (tag) * 256000000 / 48000; // ???
|
||||
*stamp = g_audio.start_time + (tag) * 256000000 / 48000; // ???
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -638,6 +628,8 @@ void libmixer_init(Module *pxThis)
|
||||
{
|
||||
libmixer = pxThis;
|
||||
|
||||
g_surmx.audio_port = ~0;
|
||||
|
||||
REG_SUB(libmixer, "surmxAAN", cellAANAddData,
|
||||
0xffffffff7c691b78,
|
||||
0xffffffff7c0802a6,
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
enum //libmixer Error Codes
|
||||
// Error Codes
|
||||
enum
|
||||
{
|
||||
CELL_LIBMIXER_ERROR_NOT_INITIALIZED = 0x80310002,
|
||||
CELL_LIBMIXER_ERROR_INVALID_PARAMATER = 0x80310003,
|
||||
@ -164,6 +165,16 @@ struct CellSurMixerChStripParam
|
||||
be_t<s32> intVal;
|
||||
};
|
||||
|
||||
struct SurMixerConfig
|
||||
{
|
||||
u32 audio_port;
|
||||
s32 priority;
|
||||
u32 ch_strips_1;
|
||||
u32 ch_strips_2;
|
||||
u32 ch_strips_6;
|
||||
u32 ch_strips_8;
|
||||
};
|
||||
|
||||
struct SSPlayer
|
||||
{
|
||||
bool m_created; // SSPlayerCreate/Remove
|
||||
|
@ -77,7 +77,7 @@ namespace detail
|
||||
|
||||
static __forceinline void func(PPUThread& CPU, const T& result)
|
||||
{
|
||||
CPU.GPR[3] = cast_ppu_gpr<T>::func(result);
|
||||
CPU.GPR[3] = cast_to_ppu_gpr<T>(result);
|
||||
}
|
||||
};
|
||||
|
||||
@ -88,7 +88,7 @@ namespace detail
|
||||
|
||||
static __forceinline void func(PPUThread& CPU, const T& result)
|
||||
{
|
||||
CPU.FPR[1] = (double)result;
|
||||
CPU.FPR[1] = result;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -966,11 +966,7 @@ int cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<u32> id, vm::ptr<void(*)(vm::p
|
||||
const u32 xid = g_FsAioReadID++;
|
||||
*id = xid;
|
||||
|
||||
{
|
||||
thread t("fsAioRead", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
t.detach();
|
||||
}
|
||||
|
||||
thread_t t("CellFsAio Reading Thread", std::bind(fsAioRead, fd, aio, xid, func));
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define MHZ (1000000)
|
||||
enum : u32
|
||||
{
|
||||
MHZ = 1000000,
|
||||
};
|
||||
|
||||
// Auxiliary functions
|
||||
u64 get_time();
|
||||
|
@ -328,6 +328,8 @@ void Emulator::Pause()
|
||||
if (InterlockedCompareExchange((volatile u32*)&m_status, Paused, Running) == Running)
|
||||
{
|
||||
SendDbgCommand(DID_PAUSED_EMU);
|
||||
|
||||
GetCallbackManager().RunPauseCallbacks(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,6 +343,8 @@ void Emulator::Resume()
|
||||
CheckStatus();
|
||||
|
||||
SendDbgCommand(DID_RESUMED_EMU);
|
||||
|
||||
GetCallbackManager().RunPauseCallbacks(false);
|
||||
}
|
||||
|
||||
void Emulator::Stop()
|
||||
@ -350,17 +354,13 @@ void Emulator::Stop()
|
||||
SendDbgCommand(DID_STOP_EMU);
|
||||
m_status = Stopped;
|
||||
|
||||
u32 uncounted = 0;
|
||||
while (true)
|
||||
while (g_thread_count)
|
||||
{
|
||||
if (g_thread_count <= uncounted)
|
||||
{
|
||||
LOG_NOTICE(HLE, "All threads stopped...");
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
LOG_NOTICE(HLE, "All threads stopped...");
|
||||
|
||||
m_rsx_callback = 0;
|
||||
|
||||
// TODO: check finalization order
|
||||
|
@ -187,9 +187,8 @@ namespace loader
|
||||
LOG_ERROR(LOADER, "Unimplemented function 0x%08x (addr=0x%x)", nid, addr);
|
||||
|
||||
vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb)
|
||||
vm::psv::write16(addr + 2, 0x0000); // index 0
|
||||
vm::psv::write16(addr + 4, 0x4770); // BX LR
|
||||
vm::psv::write16(addr + 6, 0); // null
|
||||
vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub)
|
||||
vm::psv::write32(addr + 4, nid); // nid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -385,6 +385,7 @@
|
||||
<ClInclude Include="Emu\SysCalls\Modules.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAdec.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAtrac.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAudio.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellCamera.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellDmux.h" />
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellFiber.h" />
|
||||
|
@ -1279,5 +1279,8 @@
|
||||
<ClInclude Include="Emu\Audio\XAudio2\XAudio2Thread.h">
|
||||
<Filter>Emu\Audio\XAudio2</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\SysCalls\Modules\cellAudio.h">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user