mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-04 07:40:10 +01:00
move AudioOut from orbis-kernel to rpcsx-os
This commit is contained in:
parent
5d457af7fa
commit
7e01a65117
|
|
@ -1,7 +1,5 @@
|
|||
set(CMAKE_POSITION_INDEPENDENT_CODE on)
|
||||
|
||||
find_package(sox REQUIRED)
|
||||
|
||||
add_library(obj.orbis-utils-ipc OBJECT
|
||||
src/utils/SharedMutex.cpp
|
||||
src/utils/SharedCV.cpp
|
||||
|
|
@ -73,7 +71,7 @@ add_library(obj.orbis-kernel OBJECT
|
|||
src/utils/Logs.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(obj.orbis-kernel PUBLIC orbis::kernel::config $<TARGET_OBJECTS:obj.orbis-utils-ipc> sox::sox)
|
||||
target_link_libraries(obj.orbis-kernel PUBLIC orbis::kernel::config $<TARGET_OBJECTS:obj.orbis-utils-ipc>)
|
||||
|
||||
target_include_directories(obj.orbis-kernel
|
||||
PUBLIC
|
||||
|
|
|
|||
|
|
@ -1,238 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "evf.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <sox.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace orbis {
|
||||
struct AudioOutChannelInfo {
|
||||
std::int32_t port{};
|
||||
std::int32_t idControl{};
|
||||
std::int32_t channel{};
|
||||
Ref<EventFlag> evf;
|
||||
};
|
||||
|
||||
struct AudioOutParams {
|
||||
std::uint64_t control{};
|
||||
std::uint32_t formatChannels{};
|
||||
float unk0{};
|
||||
float unk1{};
|
||||
float unk2{};
|
||||
float unk3{};
|
||||
float unk4{};
|
||||
float unk5{};
|
||||
float unk6{};
|
||||
float unk7{};
|
||||
std::uint32_t formatIsFloat{};
|
||||
std::uint64_t freq{};
|
||||
std::uint32_t formatIsStd{};
|
||||
std::uint32_t seek{};
|
||||
std::uint32_t seekPart{};
|
||||
std::uint64_t unk8{};
|
||||
std::uint32_t port{};
|
||||
std::uint32_t unk9{};
|
||||
std::uint64_t unk10{};
|
||||
std::uint32_t sampleLength{};
|
||||
};
|
||||
|
||||
struct AudioOut {
|
||||
std::mutex thrMtx;
|
||||
std::mutex soxMtx;
|
||||
std::vector<std::thread> threads;
|
||||
AudioOutChannelInfo channelInfo;
|
||||
std::atomic<bool> exit{false};
|
||||
|
||||
AudioOut() {
|
||||
if (sox_init() != SOX_SUCCESS) {
|
||||
ORBIS_LOG_FATAL("Failed to initialize sox");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
~AudioOut() {
|
||||
exit = true;
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
sox_quit();
|
||||
}
|
||||
|
||||
void start() {
|
||||
std::lock_guard lock(thrMtx);
|
||||
threads.push_back(std::thread(
|
||||
[this, channelInfo = channelInfo] { channelEntry(channelInfo); }));
|
||||
}
|
||||
|
||||
private:
|
||||
void channelEntry(AudioOutChannelInfo info) {
|
||||
char control_shm_name[32];
|
||||
char audio_shm_name[32];
|
||||
|
||||
std::snprintf(control_shm_name, sizeof(control_shm_name), "/rpcsx-shm_%d_C",
|
||||
info.idControl);
|
||||
std::snprintf(audio_shm_name, sizeof(audio_shm_name), "/rpcsx-shm_%d_%d_A",
|
||||
info.channel, info.port);
|
||||
|
||||
int controlFd =
|
||||
::shm_open(control_shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (controlFd == -1) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
struct stat controlStat;
|
||||
if (::fstat(controlFd, &controlStat)) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
auto controlPtr = reinterpret_cast<std::uint8_t *>(
|
||||
::mmap(NULL, controlStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
controlFd, 0));
|
||||
if (controlPtr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int bufferFd =
|
||||
::shm_open(audio_shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (bufferFd == -1) {
|
||||
perror("open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
struct stat bufferStat;
|
||||
if (::fstat(bufferFd, &bufferStat)) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
auto audioBuffer = ::mmap(NULL, bufferStat.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, bufferFd, 0);
|
||||
auto bitPattern = 1u << info.port;
|
||||
|
||||
auto portOffset = 32 + 0x94 * info.port * 4;
|
||||
|
||||
auto *params = reinterpret_cast<AudioOutParams *>(controlPtr + portOffset);
|
||||
|
||||
// samples length will be inited after some time, so we wait for it
|
||||
while (params->sampleLength == 0) {
|
||||
}
|
||||
|
||||
ORBIS_LOG_NOTICE("AudioOut: params", params->port, params->control,
|
||||
params->formatChannels, params->formatIsFloat,
|
||||
params->formatIsStd, params->freq, params->sampleLength);
|
||||
|
||||
unsigned inChannels = 2;
|
||||
unsigned inSamples = params->sampleLength;
|
||||
sox_rate_t sampleRate = 48000; // probably there is no point to parse
|
||||
// frequency, because it's always 48000
|
||||
if (params->formatChannels == 2 && !params->formatIsFloat) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO");
|
||||
} else if (params->formatChannels == 4 && !params->formatIsFloat) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO");
|
||||
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||
!params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH");
|
||||
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||
params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD");
|
||||
} else if (params->formatChannels == 4 && params->formatIsFloat) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO");
|
||||
} else if (params->formatChannels == 8 && params->formatIsFloat) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO");
|
||||
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||
!params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH");
|
||||
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||
params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE("AudioOut: format is "
|
||||
"ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD");
|
||||
} else {
|
||||
ORBIS_LOG_ERROR("AudioOut: unknown format type");
|
||||
}
|
||||
|
||||
sox_signalinfo_t out_si = {
|
||||
.rate = sampleRate,
|
||||
.channels = inChannels,
|
||||
.precision = SOX_SAMPLE_PRECISION,
|
||||
};
|
||||
|
||||
// need to be locked because libsox doesn't like simultaneous opening of the
|
||||
// output
|
||||
std::unique_lock lock(soxMtx);
|
||||
sox_format_t *output =
|
||||
sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
||||
soxMtx.unlock();
|
||||
|
||||
if (!output) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::vector<sox_sample_t> samples(inSamples * inChannels);
|
||||
|
||||
std::size_t clips = 0;
|
||||
SOX_SAMPLE_LOCALS;
|
||||
|
||||
while (!exit.load(std::memory_order::relaxed)) {
|
||||
if (params->control == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!params->formatIsFloat) {
|
||||
auto data = reinterpret_cast<const std::int16_t *>(audioBuffer);
|
||||
for (std::size_t i = 0; i < samples.size(); i++) {
|
||||
samples[i] = SOX_SIGNED_16BIT_TO_SAMPLE(data[i], clips);
|
||||
}
|
||||
} else {
|
||||
auto data = reinterpret_cast<const float *>(audioBuffer);
|
||||
for (std::size_t i = 0; i < samples.size(); i++) {
|
||||
samples[i] = SOX_FLOAT_32BIT_TO_SAMPLE(data[i], clips);
|
||||
}
|
||||
}
|
||||
|
||||
if (sox_write(output, samples.data(), samples.size()) != samples.size()) {
|
||||
ORBIS_LOG_ERROR("AudioOut: sox_write failed");
|
||||
}
|
||||
|
||||
// set zero to freeing audiooutput
|
||||
params->control = 0;
|
||||
|
||||
// skip sceAudioOutMix%x event
|
||||
info.evf->set(bitPattern);
|
||||
}
|
||||
|
||||
sox_close(output);
|
||||
|
||||
::munmap(audioBuffer, bufferStat.st_size);
|
||||
::munmap(controlPtr, controlStat.st_size);
|
||||
|
||||
::close(controlFd);
|
||||
::close(bufferFd);
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "AudioOut.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "evf.hpp"
|
||||
#include "ipmi.hpp"
|
||||
|
|
@ -178,7 +177,6 @@ public:
|
|||
Ref<RcBase> shmDevice;
|
||||
Ref<RcBase> dmemDevice;
|
||||
Ref<RcBase> blockpoolDevice;
|
||||
AudioOut *audioOut = nullptr;
|
||||
uint sdkVersion{};
|
||||
uint fwSdkVersion{};
|
||||
uint safeMode{};
|
||||
|
|
|
|||
196
rpcsx-os/AudioOut.cpp
Normal file
196
rpcsx-os/AudioOut.cpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
#include "AudioOut.hpp"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <orbis/evf.hpp>
|
||||
#include <orbis/utils/Logs.hpp>
|
||||
#include <sox.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
AudioOut::AudioOut() {
|
||||
if (sox_init() != SOX_SUCCESS) {
|
||||
ORBIS_LOG_FATAL("Failed to initialize sox");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
AudioOut::~AudioOut() {
|
||||
exit = true;
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
sox_quit();
|
||||
}
|
||||
|
||||
void AudioOut::start() {
|
||||
std::lock_guard lock(thrMtx);
|
||||
threads.push_back(std::thread(
|
||||
[this, channelInfo = channelInfo] { channelEntry(channelInfo); }));
|
||||
}
|
||||
|
||||
void AudioOut::channelEntry(AudioOutChannelInfo info) {
|
||||
char control_shm_name[32];
|
||||
char audio_shm_name[32];
|
||||
|
||||
std::snprintf(control_shm_name, sizeof(control_shm_name), "/rpcsx-shm_%d_C",
|
||||
info.idControl);
|
||||
std::snprintf(audio_shm_name, sizeof(audio_shm_name), "/rpcsx-shm_%d_%d_A",
|
||||
info.channel, info.port);
|
||||
|
||||
int controlFd =
|
||||
::shm_open(control_shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (controlFd == -1) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
struct stat controlStat;
|
||||
if (::fstat(controlFd, &controlStat)) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
auto controlPtr = reinterpret_cast<std::uint8_t *>(
|
||||
::mmap(NULL, controlStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
controlFd, 0));
|
||||
if (controlPtr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int bufferFd =
|
||||
::shm_open(audio_shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (bufferFd == -1) {
|
||||
perror("open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
struct stat bufferStat;
|
||||
if (::fstat(bufferFd, &bufferStat)) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
auto audioBuffer = ::mmap(NULL, bufferStat.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, bufferFd, 0);
|
||||
auto bitPattern = 1u << info.port;
|
||||
|
||||
auto portOffset = 32 + 0x94 * info.port * 4;
|
||||
|
||||
auto *params = reinterpret_cast<AudioOutParams *>(controlPtr + portOffset);
|
||||
|
||||
// samples length will be inited after some time, so we wait for it
|
||||
while (params->sampleLength == 0) {
|
||||
}
|
||||
|
||||
ORBIS_LOG_NOTICE("AudioOut: params", params->port, params->control,
|
||||
params->formatChannels, params->formatIsFloat,
|
||||
params->formatIsStd, params->freq, params->sampleLength);
|
||||
|
||||
unsigned inChannels = 2;
|
||||
unsigned inSamples = params->sampleLength;
|
||||
sox_rate_t sampleRate = 48000; // probably there is no point to parse
|
||||
// frequency, because it's always 48000
|
||||
if (params->formatChannels == 2 && !params->formatIsFloat) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO");
|
||||
} else if (params->formatChannels == 4 && !params->formatIsFloat) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO");
|
||||
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||
!params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH");
|
||||
} else if (params->formatChannels == 16 && !params->formatIsFloat &&
|
||||
params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD");
|
||||
} else if (params->formatChannels == 4 && params->formatIsFloat) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO");
|
||||
} else if (params->formatChannels == 8 && params->formatIsFloat) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO");
|
||||
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||
!params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: format is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH");
|
||||
} else if (params->formatChannels == 32 && params->formatIsFloat &&
|
||||
params->formatIsStd) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE("AudioOut: format is "
|
||||
"ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD");
|
||||
} else {
|
||||
ORBIS_LOG_ERROR("AudioOut: unknown format type");
|
||||
}
|
||||
|
||||
sox_signalinfo_t out_si = {
|
||||
.rate = sampleRate,
|
||||
.channels = inChannels,
|
||||
.precision = SOX_SAMPLE_PRECISION,
|
||||
};
|
||||
|
||||
// need to be locked because libsox doesn't like simultaneous opening of the
|
||||
// output
|
||||
std::unique_lock lock(soxMtx);
|
||||
sox_format_t *output =
|
||||
sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
||||
soxMtx.unlock();
|
||||
|
||||
if (!output) {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::vector<sox_sample_t> samples(inSamples * inChannels);
|
||||
|
||||
std::size_t clips = 0;
|
||||
SOX_SAMPLE_LOCALS;
|
||||
|
||||
while (!exit.load(std::memory_order::relaxed)) {
|
||||
if (params->control == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!params->formatIsFloat) {
|
||||
auto data = reinterpret_cast<const std::int16_t *>(audioBuffer);
|
||||
for (std::size_t i = 0; i < samples.size(); i++) {
|
||||
samples[i] = SOX_SIGNED_16BIT_TO_SAMPLE(data[i], clips);
|
||||
}
|
||||
} else {
|
||||
auto data = reinterpret_cast<const float *>(audioBuffer);
|
||||
for (std::size_t i = 0; i < samples.size(); i++) {
|
||||
samples[i] = SOX_FLOAT_32BIT_TO_SAMPLE(data[i], clips);
|
||||
}
|
||||
}
|
||||
|
||||
if (sox_write(output, samples.data(), samples.size()) != samples.size()) {
|
||||
ORBIS_LOG_ERROR("AudioOut: sox_write failed");
|
||||
}
|
||||
|
||||
// set zero to freeing audiooutput
|
||||
params->control = 0;
|
||||
|
||||
// skip sceAudioOutMix%x event
|
||||
info.evf->set(bitPattern);
|
||||
}
|
||||
|
||||
sox_close(output);
|
||||
|
||||
::munmap(audioBuffer, bufferStat.st_size);
|
||||
::munmap(controlPtr, controlStat.st_size);
|
||||
|
||||
::close(controlFd);
|
||||
::close(bufferFd);
|
||||
}
|
||||
55
rpcsx-os/AudioOut.hpp
Normal file
55
rpcsx-os/AudioOut.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <orbis/evf.hpp>
|
||||
#include <orbis/utils/Rc.hpp>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
struct AudioOutChannelInfo {
|
||||
std::int32_t port{};
|
||||
std::int32_t idControl{};
|
||||
std::int32_t channel{};
|
||||
orbis::Ref<orbis::EventFlag> evf;
|
||||
};
|
||||
|
||||
struct AudioOutParams {
|
||||
std::uint64_t control{};
|
||||
std::uint32_t formatChannels{};
|
||||
float unk0{};
|
||||
float unk1{};
|
||||
float unk2{};
|
||||
float unk3{};
|
||||
float unk4{};
|
||||
float unk5{};
|
||||
float unk6{};
|
||||
float unk7{};
|
||||
std::uint32_t formatIsFloat{};
|
||||
std::uint64_t freq{};
|
||||
std::uint32_t formatIsStd{};
|
||||
std::uint32_t seek{};
|
||||
std::uint32_t seekPart{};
|
||||
std::uint64_t unk8{};
|
||||
std::uint32_t port{};
|
||||
std::uint32_t unk9{};
|
||||
std::uint64_t unk10{};
|
||||
std::uint32_t sampleLength{};
|
||||
};
|
||||
|
||||
struct AudioOut : orbis::RcBase {
|
||||
std::mutex thrMtx;
|
||||
std::mutex soxMtx;
|
||||
std::vector<std::thread> threads;
|
||||
AudioOutChannelInfo channelInfo;
|
||||
std::atomic<bool> exit{false};
|
||||
|
||||
AudioOut();
|
||||
~AudioOut();
|
||||
|
||||
void start();
|
||||
|
||||
private:
|
||||
void channelEntry(AudioOutChannelInfo info);
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
find_package(libunwind REQUIRED)
|
||||
find_package(sox REQUIRED)
|
||||
|
||||
add_library(standalone-config INTERFACE)
|
||||
target_include_directories(standalone-config INTERFACE orbis-kernel-config)
|
||||
|
|
@ -53,6 +54,7 @@ add_executable(rpcsx-os
|
|||
iodev/cayman_reg.cpp
|
||||
|
||||
main.cpp
|
||||
AudioOut.cpp
|
||||
backtrace.cpp
|
||||
bridge.cpp
|
||||
vm.cpp
|
||||
|
|
@ -64,7 +66,7 @@ add_executable(rpcsx-os
|
|||
)
|
||||
|
||||
target_include_directories(rpcsx-os PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(rpcsx-os PUBLIC orbis::kernel amdgpu::bridge rx libcrypto libunwind::unwind-x86_64 xbyak::xbyak)
|
||||
target_link_libraries(rpcsx-os PUBLIC orbis::kernel amdgpu::bridge rx libcrypto libunwind::unwind-x86_64 xbyak::xbyak sox::sox)
|
||||
target_base_address(rpcsx-os 0x0000010000000000)
|
||||
target_compile_options(rpcsx-os PRIVATE "-mfsgsbase")
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <sys/mman.h>
|
||||
|
||||
static constexpr auto kDceControlMemoryOffset = 0;
|
||||
static constexpr auto kDceControlMemorySize = 0x10000;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include "AudioOut.hpp"
|
||||
#include "amdgpu/bridge/bridge.hpp"
|
||||
#include "backtrace.hpp"
|
||||
#include "bridge.hpp"
|
||||
|
|
@ -7,10 +8,12 @@
|
|||
#include "iodev/mbus_av.hpp"
|
||||
#include "linker.hpp"
|
||||
#include "ops.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "vfs.hpp"
|
||||
#include "vm.hpp"
|
||||
#include "xbyak/xbyak.h"
|
||||
#include <orbis/utils/Rc.hpp>
|
||||
#include <rx/Version.hpp>
|
||||
#include <rx/align.hpp>
|
||||
#include <rx/hexdump.hpp>
|
||||
|
|
@ -702,7 +705,8 @@ static bool isRpcsxGpuPid(int pid) {
|
|||
std::printf("filename is '%s'\n",
|
||||
std::filesystem::path(path).filename().c_str());
|
||||
|
||||
return std::filesystem::path(path).filename().string().starts_with("rpcsx-gpu");
|
||||
return std::filesystem::path(path).filename().string().starts_with(
|
||||
"rpcsx-gpu");
|
||||
}
|
||||
static void runRpcsxGpu() {
|
||||
const char *cmdBufferName = "/rpcsx-gpu-cmds";
|
||||
|
|
@ -1219,53 +1223,57 @@ struct SceSysAudioSystemPortAndThreadArgs {
|
|||
};
|
||||
|
||||
static void createAudioSystemObjects(orbis::Process *process) {
|
||||
auto audioOut = orbis::Ref<AudioOut>(orbis::knew<AudioOut>());
|
||||
|
||||
createIpmiServer(process, "SceSysAudioSystemIpc")
|
||||
.addSyncMethod<SceSysAudioSystemThreadArgs>(
|
||||
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;
|
||||
}
|
||||
0x12340000,
|
||||
[=](const auto &args) -> std::int32_t {
|
||||
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemCreateControl",
|
||||
args.threadId);
|
||||
audioOut->channelInfo.idControl = args.threadId;
|
||||
return 0;
|
||||
})
|
||||
.addSyncMethod<SceSysAudioSystemThreadArgs>(
|
||||
0x1234000f, [](const auto &args) -> std::int32_t {
|
||||
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);
|
||||
// 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
|
||||
}
|
||||
if (!inserted) {
|
||||
return 17; // FIXME: verify
|
||||
}
|
||||
|
||||
audioOut->channelInfo.evf = eventFlag;
|
||||
}
|
||||
audioOut->channelInfo.evf = eventFlag;
|
||||
return 0;
|
||||
})
|
||||
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
||||
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;
|
||||
}
|
||||
0x12340001,
|
||||
[=](const auto &args) -> std::int32_t {
|
||||
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemOpenPort", args.threadId,
|
||||
args.audioPort);
|
||||
audioOut->channelInfo.port = args.audioPort;
|
||||
audioOut->channelInfo.channel = args.threadId;
|
||||
return 0;
|
||||
})
|
||||
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
||||
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();
|
||||
}
|
||||
0x12340002,
|
||||
[=](const auto &args) -> std::int32_t {
|
||||
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStartListening",
|
||||
args.threadId, args.audioPort);
|
||||
|
||||
audioOut->start();
|
||||
return 0;
|
||||
})
|
||||
.addSyncMethod<SceSysAudioSystemPortAndThreadArgs>(
|
||||
0x12340006, [](const auto &args) -> std::int32_t {
|
||||
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStopListening", args.audioPort, args.threadId);
|
||||
0x12340006, [=](const auto &args) -> std::int32_t {
|
||||
ORBIS_LOG_TODO("IPMI: SceSysAudioSystemStopListening",
|
||||
args.audioPort, args.threadId);
|
||||
// TODO: implement
|
||||
return 0;
|
||||
});
|
||||
|
|
@ -1813,10 +1821,6 @@ int main(int argc, const char *argv[]) {
|
|||
rx::vm::initialize(initProcess->pid);
|
||||
runRpcsxGpu();
|
||||
|
||||
if (enableAudio) {
|
||||
orbis::g_context.audioOut = orbis::knew<orbis::AudioOut>();
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
|
||||
initProcess->sysent = &orbis::ps4_sysvec;
|
||||
|
|
@ -1987,7 +1991,7 @@ int main(int argc, const char *argv[]) {
|
|||
|
||||
if (!enableAudio) {
|
||||
launchDaemon(mainThread, "/system/sys/orbis_audiod.elf",
|
||||
{"/system/sys/orbis_audiod.elf"}, {});
|
||||
{"/system/sys/orbis_audiod.elf"}, {});
|
||||
}
|
||||
status = ps4Exec(mainThread, execEnv, std::move(executableModule),
|
||||
ps4Argv, {});
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
|
|
|||
Loading…
Reference in a new issue