Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cellAudio: Move and partially fix _mxr000 hack #14501

Merged
merged 1 commit into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 93 additions & 10 deletions rpcs3/Emu/Cell/Modules/cellAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

LOG_CHANNEL(cellAudio);

extern void lv2_sleep(u64 timeout, ppu_thread* ppu = nullptr);

vm::gvar<char, AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT> g_audio_buffer;

struct alignas(16) aligned_index_t
Expand Down Expand Up @@ -1252,8 +1254,6 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32

auto& g_audio = g_fxo->get<cell_audio>();

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
{
return CELL_AUDIO_ERROR_NOT_INIT;
Expand Down Expand Up @@ -1319,6 +1319,16 @@ error_code cellAudioPortOpen(vm::ptr<CellAudioPortParam> audioParam, vm::ptr<u32
cellAudio.todo("cellAudioPortOpen(): unknown attributes (0x%llx)", attr);
}

// Waiting for VSH and doing some more things
lv2_sleep(200);

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
{
return CELL_AUDIO_ERROR_NOT_INIT;
}

// Open audio port
audio_port* port = g_audio.open_port();

Expand Down Expand Up @@ -1410,8 +1420,6 @@ error_code cellAudioPortStart(u32 portNum)

auto& g_audio = g_fxo->get<cell_audio>();

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
{
return CELL_AUDIO_ERROR_NOT_INIT;
Expand All @@ -1422,6 +1430,16 @@ error_code cellAudioPortStart(u32 portNum)
return CELL_AUDIO_ERROR_PARAM;
}

// Waiting for VSH
lv2_sleep(30);

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
{
return CELL_AUDIO_ERROR_NOT_INIT;
}

switch (audio_port_state state = g_audio.ports[portNum].state.compare_and_swap(audio_port_state::opened, audio_port_state::started))
{
case audio_port_state::closed: return CELL_AUDIO_ERROR_PORT_NOT_OPEN;
Expand Down Expand Up @@ -1650,10 +1668,69 @@ error_code cellAudioCreateNotifyEventQueueEx(ppu_thread& ppu, vm::ptr<u32> id, v
return AudioCreateNotifyEventQueue(ppu, id, key, queue_type);
}

error_code AudioSetNotifyEventQueue(u64 key, u32 iFlags)
error_code AudioSetNotifyEventQueue(ppu_thread& ppu, u64 key, u32 iFlags)
{
auto& g_audio = g_fxo->get<cell_audio>();

if (!g_audio.init)
{
return CELL_AUDIO_ERROR_NOT_INIT;
}

// Waiting for VSH
lv2_sleep(20, &ppu);

// Dirty hack for sound: confirm the creation of _mxr000 event queue by _cellsurMixerMain thread
constexpr u64 c_mxr000 = 0x8000cafe0246030;

if (key == c_mxr000 || key == 0)
{
bool has_sur_mixer_thread = false;

for (usz count = 0; !lv2_event_queue::find(c_mxr000) && count < 100; count++)
{
if (has_sur_mixer_thread || idm::select<named_thread<ppu_thread>>([&](u32 id, named_thread<ppu_thread>& test_ppu)
{
// Confirm thread existence
if (id == ppu.id)
{
return false;
}

const auto ptr = test_ppu.ppu_tname.load();

if (!ptr)
{
return false;
}

return *ptr == "_cellsurMixerMain"sv;
}).ret)
{
has_sur_mixer_thread = true;
}
else
{
break;
}

if (ppu.is_stopped())
{
ppu.state += cpu_flag::again;
return {};
}

cellAudio.error("AudioSetNotifyEventQueue(): Waiting for _mxr000. x%d", count);

lv2_sleep(50'000, &ppu);
}

if (has_sur_mixer_thread && lv2_event_queue::find(c_mxr000))
{
key = c_mxr000;
}
}

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
Expand Down Expand Up @@ -1687,35 +1764,41 @@ error_code AudioSetNotifyEventQueue(u64 key, u32 iFlags)
}

// Set unique source associated with the key
g_audio.keys.push_back({
g_audio.keys.push_back
({
.start_period = g_audio.event_period,
.flags = iFlags,
.source = ((process_getpid() + u64{}) << 32) + lv2_event_port::id_base + (g_audio.key_count++ * lv2_event_port::id_step),
.ack_timestamp = 0,
.port = std::move(q)
});

g_audio.key_count %= lv2_event_port::id_count;

return CELL_OK;
}

error_code cellAudioSetNotifyEventQueue(u64 key)
error_code cellAudioSetNotifyEventQueue(ppu_thread& ppu, u64 key)
{
ppu.state += cpu_flag::wait;

cellAudio.warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);

return AudioSetNotifyEventQueue(key, 0);
return AudioSetNotifyEventQueue(ppu, key, 0);
}

error_code cellAudioSetNotifyEventQueueEx(u64 key, u32 iFlags)
error_code cellAudioSetNotifyEventQueueEx(ppu_thread& ppu, u64 key, u32 iFlags)
{
ppu.state += cpu_flag::wait;

cellAudio.todo("cellAudioSetNotifyEventQueueEx(key=0x%llx, iFlags=0x%x)", key, iFlags);

if (iFlags & (~0u >> 5))
{
return CELL_AUDIO_ERROR_PARAM;
}

return AudioSetNotifyEventQueue(key, iFlags);
return AudioSetNotifyEventQueue(ppu, key, iFlags);
}

error_code AudioRemoveNotifyEventQueue(u64 key, u32 iFlags)
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/Modules/cellGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ void disc_change_manager::insert_disc(u32 disc_type, std::string title_id)
});
}

void lv2_sleep(u64 timeout, ppu_thread* ppu = nullptr)
extern void lv2_sleep(u64 timeout, ppu_thread* ppu = nullptr)
{
if (!ppu)
{
Expand Down
26 changes: 0 additions & 26 deletions rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,32 +591,6 @@ error_code sys_ppu_thread_start(ppu_thread& ppu, u32 thread_id)
{
thread->cmd_notify++;
thread->cmd_notify.notify_one();

// Dirty hack for sound: confirm the creation of _mxr000 event queue
if (*thread->ppu_tname.load() == "_cellsurMixerMain"sv)
{
ppu.check_state();
lv2_obj::sleep(ppu);

while (!idm::select<lv2_obj, lv2_event_queue>([](u32, lv2_event_queue& eq)
{
//some games do not set event queue name, though key seems constant for them
return (eq.name == "_mxr000\0"_u64) || (eq.key == 0x8000cafe02460300);
}))
{
if (ppu.is_stopped())
{
return {};
}

thread_ctrl::wait_for(50000);
}

if (ppu.test_stopped())
{
return 0;
}
}
}

return CELL_OK;
Expand Down