diff --git a/orbis-kernel/include/orbis/AudioOut.hpp b/orbis-kernel/include/orbis/AudioOut.hpp index fb96a109..d3d370af 100644 --- a/orbis-kernel/include/orbis/AudioOut.hpp +++ b/orbis-kernel/include/orbis/AudioOut.hpp @@ -198,7 +198,10 @@ struct AudioOut { SOX_SAMPLE_LOCALS; while (!exit.load(std::memory_order::relaxed)) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + if (params->control == 0) { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + continue; + } if (!params->formatIsFloat) { auto data = reinterpret_cast(audioBuffer); @@ -216,11 +219,11 @@ struct AudioOut { ORBIS_LOG_ERROR("AudioOut: sox_write failed"); } - // skip sceAudioOutMix%x event - info.evf->set(bitPattern); - // set zero to freeing audiooutput params->control = 0; + + // skip sceAudioOutMix%x event + info.evf->set(bitPattern); } sox_close(output); diff --git a/rpcsx-os/main.cpp b/rpcsx-os/main.cpp index 86c769ba..97da11d9 100644 --- a/rpcsx-os/main.cpp +++ b/rpcsx-os/main.cpp @@ -1209,6 +1209,68 @@ static void createSysAvControlObjects(orbis::Process *process) { createShm("/SceAvSetting", 0xa02, 0x1a4, 4096); } +struct SceSysAudioSystemThreadArgs { + uint32_t threadId; +}; + +struct SceSysAudioSystemPortAndThreadArgs { + uint32_t audioPort; + uint32_t threadId; +}; + +static void createAudioSystemObjects(orbis::Process *process) { + createIpmiServer(process, "SceSysAudioSystemIpc") + .addSyncMethod( + 0x12340000, [](const auto &args) -> std::int32_t { + ORBIS_LOG_TODO("IPMI: SceSysAudioSystemCreateControl", args.threadId); + if (auto audioOut = orbis::g_context.audioOut) { + audioOut->channelInfo.idControl = args.threadId; + } + return 0; + }) + .addSyncMethod( + 0x1234000f, [](const auto &args) -> std::int32_t { + ORBIS_LOG_TODO("IPMI: SceSysAudioSystemOpenMixFlag", args.threadId); + if (auto audioOut = orbis::g_context.audioOut) { + // very bad + char buffer[32]; + std::snprintf(buffer, sizeof(buffer), "sceAudioOutMix%x", + args.threadId); + auto [eventFlag, inserted] = orbis::g_context.createEventFlag(buffer, 0x100, 0); + + if (!inserted) { + return 17; // FIXME: verify + } + + audioOut->channelInfo.evf = eventFlag; + } + return 0; + }) + .addSyncMethod( + 0x12340001, [](const auto &args) -> std::int32_t { + ORBIS_LOG_TODO("IPMI: SceSysAudioSystemOpenPort", args.threadId, args.audioPort); + if (auto audioOut = orbis::g_context.audioOut) { + audioOut->channelInfo.port = args.audioPort; + audioOut->channelInfo.channel = args.threadId; + } + return 0; + }) + .addSyncMethod( + 0x12340002, [](const auto &args) -> std::int32_t { + ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStartListening", args.threadId, args.audioPort); + if (auto audioOut = orbis::g_context.audioOut) { + audioOut->start(); + } + return 0; + }) + .addSyncMethod( + 0x12340006, [](const auto &args) -> std::int32_t { + ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStopListening", args.audioPort, args.threadId); + // TODO: implement + return 0; + }); +} + struct SceMbusIpcAddHandleByUserIdMethodArgs { orbis::uint32_t unk; // 0 orbis::uint32_t deviceId; @@ -1899,6 +1961,9 @@ int main(int argc, const char *argv[]) { createSysCoreObjects(initProcess); createGnmCompositorObjects(initProcess); createShellCoreObjects(initProcess); + if (enableAudio) { + createAudioSystemObjects(initProcess); + } // ? createIpmiServer(initProcess, "SceCdlgRichProf"); @@ -1920,8 +1985,10 @@ int main(int argc, const char *argv[]) { createEventFlag("SceSaveDataMemoryRUI00000010", 0x120, 1); initProcess->cwd = "/app0/"; - launchDaemon(mainThread, "/system/sys/orbis_audiod.elf", + if (!enableAudio) { + launchDaemon(mainThread, "/system/sys/orbis_audiod.elf", {"/system/sys/orbis_audiod.elf"}, {}); + } status = ps4Exec(mainThread, execEnv, std::move(executableModule), ps4Argv, {}); }