Skip to content

Commit

Permalink
cellAudio: Move and partially fix _mxr000 hack
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Aug 18, 2023
1 parent e410841 commit 31cb63a
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 37 deletions.
98 changes: 88 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,64 @@ 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
if (key == 0x8000cafe0246030 || key == 0)
{
key = 0x8000cafe0246030;

bool has_sur_mixer_thread = false;

for (usz count = 0; !lv2_event_queue::find(key) && 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);
}
}

std::lock_guard lock(g_audio.mutex);

if (!g_audio.init)
Expand Down Expand Up @@ -1687,35 +1759,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

0 comments on commit 31cb63a

Please sign in to comment.