mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
[orbis-kernel] AudioOut: refactoring
This commit is contained in:
parent
8f0a90d24b
commit
3d8cc28acd
|
|
@ -1,280 +1,234 @@
|
|||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <forward_list>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "evf.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <sys/ucontext.h>
|
||||
#include <thread>
|
||||
#include <ucontext.h>
|
||||
#include <utility>
|
||||
#include <cstdio>
|
||||
#include "sys/sysproto.hpp"
|
||||
#include <pthread.h>
|
||||
#include <sox.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
struct args {
|
||||
int32_t audioPort;
|
||||
int32_t idControl;
|
||||
int32_t idAudio;
|
||||
orbis::Thread *thread;
|
||||
int32_t evfId;
|
||||
namespace orbis {
|
||||
struct AudioOutChannelInfo {
|
||||
std::int32_t port{};
|
||||
std::int32_t idControl{};
|
||||
std::int32_t channel{};
|
||||
Ref<EventFlag> evf;
|
||||
};
|
||||
|
||||
int msleep(long msec)
|
||||
{
|
||||
struct timespec ts;
|
||||
int res;
|
||||
struct AudioOut {
|
||||
std::mutex thrMtx;
|
||||
std::vector<std::thread> threads;
|
||||
AudioOutChannelInfo channelInfo;
|
||||
std::atomic<bool> exit{false};
|
||||
|
||||
if (msec < 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
AudioOut() {
|
||||
if (sox_init() != SOX_SUCCESS) {
|
||||
ORBIS_LOG_FATAL("Failed to initialize sox");
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
ts.tv_sec = msec / 1000;
|
||||
ts.tv_nsec = (msec % 1000) * 1000000;
|
||||
~AudioOut() {
|
||||
exit = true;
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
sox_quit();
|
||||
}
|
||||
|
||||
do {
|
||||
res = nanosleep(&ts, &ts);
|
||||
} while (res && errno == EINTR);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void DumpHex(const void* data, size_t size) {
|
||||
char ascii[17];
|
||||
size_t i, j;
|
||||
ascii[16] = '\0';
|
||||
for (i = 0; i < size; ++i) {
|
||||
printf("%02X ", ((unsigned char*)data)[i]);
|
||||
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
|
||||
ascii[i % 16] = ((unsigned char*)data)[i];
|
||||
} else {
|
||||
ascii[i % 16] = '.';
|
||||
}
|
||||
if ((i+1) % 8 == 0 || i+1 == size) {
|
||||
printf(" ");
|
||||
if ((i+1) % 16 == 0) {
|
||||
printf("| %s \n", ascii);
|
||||
} else if (i+1 == size) {
|
||||
ascii[(i+1) % 16] = '\0';
|
||||
if ((i+1) % 16 <= 8) {
|
||||
printf(" ");
|
||||
}
|
||||
for (j = (i+1) % 16; j < 16; ++j) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("| %s \n", ascii);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * loop(void *vargp)
|
||||
{
|
||||
size_t control_shm_size = 0x10000;
|
||||
size_t audio_shm_size = 65536;
|
||||
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];
|
||||
|
||||
sprintf(control_shm_name, "/rpcsx-shm_%d_C", ((struct args*)vargp)->idControl);
|
||||
sprintf(audio_shm_name, "/rpcsx-shm_%d_%d_A", ((struct args*)vargp)->idAudio, ((struct args*)vargp)->audioPort);
|
||||
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);
|
||||
int controlFd =
|
||||
::shm_open(control_shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (controlFd == -1) {
|
||||
perror("shm_open");
|
||||
exit(EXIT_FAILURE);
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
void *controlPtr = mmap(NULL, control_shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, controlFd, 0);
|
||||
|
||||
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");
|
||||
exit(EXIT_FAILURE);
|
||||
perror("mmap");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int audioFd = shm_open(audio_shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (audioFd == -1) {
|
||||
int bufferFd =
|
||||
::shm_open(audio_shm_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
if (bufferFd == -1) {
|
||||
perror("open");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void *audioPtr = mmap(NULL, audio_shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, audioFd, 0);
|
||||
|
||||
int64_t controlPtrWithOffset = (int64_t)(controlPtr + 8);
|
||||
|
||||
int32_t bitPattern = 1 << ((struct args*)vargp)->audioPort;
|
||||
|
||||
int firstNonEmptyByteIndex;
|
||||
|
||||
for (size_t i = 24; i < control_shm_size; ++i) {
|
||||
if (*((char *)controlPtr + i) > 0) {
|
||||
firstNonEmptyByteIndex = i - 8;
|
||||
break;
|
||||
}
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int outParamFirstByte = *((char *)controlPtr + firstNonEmptyByteIndex + 8);
|
||||
int isFloatByte = *((char *)controlPtr + firstNonEmptyByteIndex + 44);
|
||||
// int outParamThirdByte = *((char *)controlPtr + firstNonEmptyByteIndex + 44); // need to find the third index
|
||||
int in_channels = 2, in_samples = 256, sample_rate = 48000; // probably there is no point to parse frequency, because it's always 48000
|
||||
if (outParamFirstByte == 2 && isFloatByte == 0) {
|
||||
in_channels = 1;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO\n");
|
||||
struct stat bufferStat;
|
||||
if (::fstat(bufferFd, &bufferStat)) {
|
||||
perror("shm_open");
|
||||
std::abort();
|
||||
}
|
||||
if (outParamFirstByte == 4 && isFloatByte == 0) {
|
||||
in_channels = 2;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO\n");
|
||||
|
||||
auto audioBuffer = ::mmap(NULL, bufferStat.st_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, bufferFd, 0);
|
||||
auto bitPattern = 1u << info.port;
|
||||
|
||||
int firstNonEmptyByteIndex = -1;
|
||||
|
||||
for (std::size_t i = 24; i < controlStat.st_size; ++i) {
|
||||
if (controlPtr[i] != 0) {
|
||||
firstNonEmptyByteIndex = i - 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: following line triggers error, investigate _C shm layout
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
if (exit.load(std::memory_order::relaxed)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outParamFirstByte == 16 && isFloatByte == 0) {
|
||||
in_channels = 8;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH\n");
|
||||
|
||||
if (firstNonEmptyByteIndex < 0) {
|
||||
ORBIS_LOG_ERROR("AudioOut: Failed to find first non zero byte index");
|
||||
std::abort();
|
||||
}
|
||||
if (outParamFirstByte == 4 && isFloatByte == 1) {
|
||||
in_channels = 1;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO\n");
|
||||
|
||||
int outParamFirstByte = controlPtr[firstNonEmptyByteIndex + 8];
|
||||
int isFloat = controlPtr[firstNonEmptyByteIndex + 44];
|
||||
|
||||
// int outParamThirdByte = *((char *)controlPtr + firstNonEmptyByteIndex +
|
||||
// 44); // need to find the third index
|
||||
|
||||
unsigned inChannels = 2;
|
||||
unsigned inSamples = 256;
|
||||
sox_rate_t sampleRate = 48000; // probably there is no point to parse
|
||||
// frequency, because it's always 48000
|
||||
if (outParamFirstByte == 2 && isFloat == 0) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_MONO");
|
||||
} else if (outParamFirstByte == 4 && isFloat == 0) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_STEREO");
|
||||
} else if (outParamFirstByte == 16 && isFloat == 0) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH");
|
||||
} else if (outParamFirstByte == 4 && isFloat == 1) {
|
||||
inChannels = 1;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_MONO");
|
||||
} else if (outParamFirstByte == 8 && isFloat == 1) {
|
||||
inChannels = 2;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO");
|
||||
} else if (outParamFirstByte == 32 && isFloat == 1) {
|
||||
inChannels = 8;
|
||||
ORBIS_LOG_NOTICE(
|
||||
"AudioOut: outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH");
|
||||
} else {
|
||||
ORBIS_LOG_ERROR("AudioOut: unknown output type");
|
||||
}
|
||||
if (outParamFirstByte == 8 && isFloatByte == 1) {
|
||||
in_channels = 2;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_STEREO\n");
|
||||
}
|
||||
if (outParamFirstByte == 32 && isFloatByte == 1) {
|
||||
in_channels = 8;
|
||||
printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH\n");
|
||||
}
|
||||
// // it's need third byte
|
||||
// if (outParamFirstByte == 16 && outParamSecondByte == 0 && outParamThirdByte == 1) {
|
||||
|
||||
// it's need third byte
|
||||
// if (outParamFirstByte == 16 && outParamSecondByte == 0 &&
|
||||
// outParamThirdByte
|
||||
// == 1) {
|
||||
// printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_S16_8CH_STD");
|
||||
// }
|
||||
// if (outParamFirstByte == 32 && outParamSecondByte == 1 && outParamThirdByte == 1) {
|
||||
// if (outParamFirstByte == 32 && outParamSecondByte == 1 &&
|
||||
// outParamThirdByte
|
||||
// == 1) {
|
||||
// printf("outputParam is ORBIS_AUDIO_OUT_PARAM_FORMAT_FLOAT_8CH_STD");
|
||||
// }
|
||||
|
||||
// length byte will be inited after some time, so we wait for it
|
||||
int samplesLengthByte;
|
||||
while(true) {
|
||||
samplesLengthByte = *((char *)controlPtr + firstNonEmptyByteIndex + 97);
|
||||
int samplesLengthByte = 0;
|
||||
while (true) {
|
||||
samplesLengthByte = controlPtr[firstNonEmptyByteIndex + 97];
|
||||
if (samplesLengthByte > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in_samples = samplesLengthByte * 256;
|
||||
inSamples = samplesLengthByte * 256;
|
||||
|
||||
if (sox_init() != SOX_SUCCESS) {
|
||||
exit(1);
|
||||
}
|
||||
sox_signalinfo_t out_si = {
|
||||
.rate = sampleRate,
|
||||
.channels = inChannels,
|
||||
.precision = SOX_SAMPLE_PRECISION,
|
||||
};
|
||||
|
||||
sox_signalinfo_t out_si = {};
|
||||
out_si.rate = sample_rate;
|
||||
out_si.channels = in_channels;
|
||||
out_si.precision = SOX_SAMPLE_PRECISION;
|
||||
|
||||
sox_format_t* output
|
||||
= sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
||||
sox_format_t *output =
|
||||
sox_open_write("default", &out_si, NULL, "alsa", NULL, NULL);
|
||||
if (!output) {
|
||||
exit(1);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
sox_sample_t samples[in_samples * in_channels];
|
||||
std::vector<sox_sample_t> samples(inSamples * inChannels);
|
||||
|
||||
std::size_t clips = 0;
|
||||
SOX_SAMPLE_LOCALS;
|
||||
|
||||
while (!exit.load(std::memory_order::relaxed)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
if (isFloat == 0) {
|
||||
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");
|
||||
}
|
||||
|
||||
size_t clips = 0; SOX_SAMPLE_LOCALS;
|
||||
size_t n_samples;
|
||||
int size;
|
||||
if (isFloatByte == 0) {
|
||||
size = in_samples * in_channels * sizeof(int16_t);
|
||||
n_samples = size / sizeof(int16_t);
|
||||
} else if (isFloatByte == 1) {
|
||||
size = in_samples * in_channels * sizeof(float);
|
||||
n_samples = size / sizeof(float);
|
||||
}
|
||||
while(true) {
|
||||
// skip sceAudioOutMix%x event
|
||||
sys_evf_set(((struct args*)vargp)->thread, ((struct args*)vargp)->evfId, bitPattern);
|
||||
info.evf->set(bitPattern);
|
||||
|
||||
// set zero to freeing audiooutput
|
||||
for (size_t i = 0; i < 8; ++i) {
|
||||
*((char *)controlPtr + firstNonEmptyByteIndex + i) = 0x00;
|
||||
}
|
||||
|
||||
// DumpHex(audioPtr, 1000);
|
||||
// sleep 1ms
|
||||
msleep(1);
|
||||
if (isFloatByte == 0) {
|
||||
int16_t data[size];
|
||||
memcpy(data, audioPtr, size);
|
||||
for (size_t n = 0; n < n_samples; n++) {
|
||||
samples[n] = SOX_SIGNED_16BIT_TO_SAMPLE(data[n], clips);
|
||||
}
|
||||
// free(data);
|
||||
}
|
||||
if (isFloatByte == 1) {
|
||||
float data[size];
|
||||
memcpy(data, audioPtr, size);
|
||||
for (size_t n = 0; n < n_samples; n++) {
|
||||
samples[n] = SOX_FLOAT_32BIT_TO_SAMPLE(data[n], clips);
|
||||
}
|
||||
// free(data);
|
||||
}
|
||||
|
||||
if (sox_write(output, samples, n_samples) != n_samples) {
|
||||
exit(1);
|
||||
controlPtr[firstNonEmptyByteIndex + i] = 0;
|
||||
}
|
||||
}
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
namespace orbis {
|
||||
class AudioOut {
|
||||
public:
|
||||
int32_t audioPort;
|
||||
int32_t idControl;
|
||||
int32_t idAudio;
|
||||
int32_t evfId;
|
||||
AudioOut() {
|
||||
sox_close(output);
|
||||
|
||||
::munmap(audioBuffer, bufferStat.st_size);
|
||||
::munmap(controlPtr, controlStat.st_size);
|
||||
|
||||
::close(controlFd);
|
||||
::close(bufferFd);
|
||||
}
|
||||
|
||||
~AudioOut() {
|
||||
}
|
||||
|
||||
static AudioOut& getInstance() {
|
||||
static AudioOut instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void setPortId(int32_t port) {
|
||||
this->audioPort = port;
|
||||
}
|
||||
|
||||
void setControlId(int32_t id) {
|
||||
this->idControl = id;
|
||||
}
|
||||
|
||||
void setAudioId(int32_t id) {
|
||||
this->idAudio = id;
|
||||
}
|
||||
|
||||
void setEvfId(int32_t evfId) {
|
||||
this->evfId = evfId;
|
||||
}
|
||||
|
||||
void start(orbis::Thread *thread) {
|
||||
Ref<File> file;
|
||||
// probably need to close
|
||||
auto result = thread->tproc->ops->open(thread, "/dev/audioHack", 0, 0, &file);
|
||||
if (result.value() == 0) {
|
||||
struct args *threadArgs = (struct args *)malloc(sizeof(struct args));
|
||||
threadArgs->audioPort = this->audioPort;
|
||||
threadArgs->idControl = this->idControl;
|
||||
threadArgs->idAudio = this->idAudio;
|
||||
threadArgs->thread = thread;
|
||||
threadArgs->evfId = this->evfId;
|
||||
|
||||
pthread_t thread_id;
|
||||
pthread_create(&thread_id, NULL, loop, (void *)threadArgs);
|
||||
}
|
||||
}
|
||||
private:
|
||||
AudioOut( const AudioOut&);
|
||||
AudioOut& operator=( AudioOut& );
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "utils/SharedCV.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
|
||||
#include "AudioOut.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "orbis/thread/types.hpp"
|
||||
#include <algorithm>
|
||||
|
|
@ -150,6 +151,7 @@ public:
|
|||
Ref<RcBase> shmDevice;
|
||||
Ref<RcBase> dmemDevice;
|
||||
Ref<RcBase> blockpoolDevice;
|
||||
AudioOut *audioOut = nullptr;
|
||||
|
||||
private:
|
||||
mutable pthread_mutex_t m_heap_mtx;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "evf.hpp"
|
||||
#include "module/ModuleInfo.hpp"
|
||||
#include "module/ModuleInfoEx.hpp"
|
||||
#include "orbis/AudioOut.hpp"
|
||||
#include "orbis/time.hpp"
|
||||
#include "osem.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
|
|
@ -11,7 +12,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include "orbis/AudioOut.hpp"
|
||||
|
||||
orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op,
|
||||
ptr<void> buf, uint nbuf) {
|
||||
|
|
@ -1146,78 +1146,85 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
uint32_t channelId;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs) == 0x4);
|
||||
static_assert(
|
||||
sizeof(SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs) ==
|
||||
0x4);
|
||||
|
||||
if (dataInfo.size != sizeof(SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs)) {
|
||||
if (dataInfo.size !=
|
||||
sizeof(SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs args;
|
||||
uread(args, ptr<SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs>(dataInfo.data));
|
||||
uread(args, ptr<SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs>(
|
||||
dataInfo.data));
|
||||
|
||||
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs", args.channelId);
|
||||
AudioOut& ao = AudioOut::getInstance();
|
||||
ao.setControlId(args.channelId);
|
||||
}
|
||||
if (syncCallParams.method == 0x1234000f) { // create event flag
|
||||
ORBIS_LOG_TODO(
|
||||
"impi: SceSysAudioSystemIpcCheckSharedMemoryControlMethodArgs",
|
||||
args.channelId);
|
||||
if (auto audioOut = g_context.audioOut) {
|
||||
audioOut->channelInfo.idControl = args.channelId;
|
||||
}
|
||||
} else if (syncCallParams.method == 0x1234000f) { // create event flag
|
||||
struct SceSysAudioSystemIpcCreateEventFlagMethodArgs {
|
||||
uint32_t channelId;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SceSysAudioSystemIpcCreateEventFlagMethodArgs) == 0x4);
|
||||
static_assert(sizeof(SceSysAudioSystemIpcCreateEventFlagMethodArgs) ==
|
||||
0x4);
|
||||
|
||||
if (dataInfo.size != sizeof(SceSysAudioSystemIpcCreateEventFlagMethodArgs)) {
|
||||
if (dataInfo.size !=
|
||||
sizeof(SceSysAudioSystemIpcCreateEventFlagMethodArgs)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
SceSysAudioSystemIpcCreateEventFlagMethodArgs args;
|
||||
uread(args, ptr<SceSysAudioSystemIpcCreateEventFlagMethodArgs>(dataInfo.data));
|
||||
uread(args, ptr<SceSysAudioSystemIpcCreateEventFlagMethodArgs>(
|
||||
dataInfo.data));
|
||||
|
||||
// very bad
|
||||
char buffer[32];
|
||||
sprintf(buffer, "sceAudioOutMix%x", args.channelId);
|
||||
// const char* eventName = &buffer;
|
||||
int32_t attrs = 0x100;
|
||||
EventFlag *eventFlag;
|
||||
if (attrs & kEvfAttrShared) {
|
||||
auto [insertedEvf, inserted] =
|
||||
thread->tproc->context->createEventFlag(buffer, attrs, 0);
|
||||
if (auto audioOut = g_context.audioOut) {
|
||||
// very bad
|
||||
char buffer[32];
|
||||
std::snprintf(buffer, sizeof(buffer), "sceAudioOutMix%x",
|
||||
args.channelId);
|
||||
// const char* eventName = &buffer;
|
||||
auto [eventFlag, inserted] = thread->tproc->context->createEventFlag(
|
||||
buffer, kEvfAttrShared, 0);
|
||||
|
||||
if (!inserted) {
|
||||
return ErrorCode::EXIST; // FIXME: verify
|
||||
}
|
||||
|
||||
eventFlag = insertedEvf;
|
||||
} else {
|
||||
eventFlag = knew<EventFlag>(attrs, 0);
|
||||
std::strncpy(eventFlag->name, buffer, 32);
|
||||
audioOut->channelInfo.evf = eventFlag;
|
||||
}
|
||||
|
||||
int32_t audioOutMixId = thread->tproc->evfMap.insert(eventFlag);
|
||||
AudioOut& ao = AudioOut::getInstance();
|
||||
ao.setEvfId(audioOutMixId);
|
||||
}
|
||||
if (syncCallParams.method == 0x12340001) { // check shared memory audio
|
||||
} else if (syncCallParams.method ==
|
||||
0x12340001) { // check shared memory audio
|
||||
struct SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs {
|
||||
uint32_t audioPort;
|
||||
uint32_t channelId;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs) == 0x8);
|
||||
static_assert(
|
||||
sizeof(SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs) ==
|
||||
0x8);
|
||||
|
||||
if (dataInfo.size != sizeof(SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs)) {
|
||||
if (dataInfo.size !=
|
||||
sizeof(SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs args;
|
||||
uread(args, ptr<SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs>(dataInfo.data));
|
||||
uread(args, ptr<SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs>(
|
||||
dataInfo.data));
|
||||
|
||||
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs", args.audioPort, args.channelId);
|
||||
AudioOut& ao = AudioOut::getInstance();
|
||||
ao.setPortId(args.audioPort);
|
||||
ao.setAudioId(args.channelId);
|
||||
}
|
||||
if (syncCallParams.method == 0x12340002) { // something something open
|
||||
ORBIS_LOG_TODO(
|
||||
"impi: SceSysAudioSystemIpcCheckSharedMemoryAudioMethodArgs",
|
||||
args.audioPort, args.channelId);
|
||||
if (auto audioOut = g_context.audioOut) {
|
||||
audioOut->channelInfo.port = args.audioPort;
|
||||
audioOut->channelInfo.channel = args.channelId;
|
||||
}
|
||||
} else if (syncCallParams.method == 0x12340002) { // something like open
|
||||
struct SceSysAudioSystemIpcSomethingMethodArgs {
|
||||
uint32_t arg1;
|
||||
uint32_t arg2;
|
||||
|
|
@ -1230,12 +1237,16 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
}
|
||||
|
||||
SceSysAudioSystemIpcSomethingMethodArgs args;
|
||||
uread(args, ptr<SceSysAudioSystemIpcSomethingMethodArgs>(dataInfo.data));
|
||||
uread(args,
|
||||
ptr<SceSysAudioSystemIpcSomethingMethodArgs>(dataInfo.data));
|
||||
|
||||
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcSomethingMethodArgs", args.arg1, args.arg2);
|
||||
// here startToListen
|
||||
AudioOut& ao = AudioOut::getInstance();
|
||||
ao.start(thread);
|
||||
ORBIS_LOG_TODO("impi: SceSysAudioSystemIpcSomethingMethodArgs",
|
||||
args.arg1, args.arg2);
|
||||
|
||||
if (auto audioOut = g_context.audioOut) {
|
||||
// here startToListen
|
||||
audioOut->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1326,6 +1337,10 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
return {};
|
||||
}
|
||||
|
||||
if (op == 0x243) {
|
||||
return uwrite<uint>(result, 0);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_get_gpo(Thread *thread /* TODO */) {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,6 @@ struct StackWriter {
|
|||
};
|
||||
|
||||
static bool g_traceSyscalls = false;
|
||||
static bool g_enableAudio = false;
|
||||
static const char *getSyscallName(orbis::Thread *thread, int sysno) {
|
||||
auto sysvec = thread->tproc->sysent;
|
||||
|
||||
|
|
@ -342,9 +341,6 @@ static int ps4Exec(orbis::Thread *mainThread,
|
|||
rx::vfs::mount("/dev/rng", createRngCharacterDevice());
|
||||
rx::vfs::mount("/dev/sbl_srv", createSblSrvCharacterDevice());
|
||||
rx::vfs::mount("/dev/ajm", createAjmCharacterDevice());
|
||||
if (g_enableAudio) {
|
||||
rx::vfs::mount("/dev/audioHack", createNullCharacterDevice());
|
||||
}
|
||||
|
||||
orbis::Ref<orbis::File> stdinFile;
|
||||
orbis::Ref<orbis::File> stdoutFile;
|
||||
|
|
@ -531,6 +527,8 @@ int main(int argc, const char *argv[]) {
|
|||
setupSigHandlers();
|
||||
rx::vfs::initialize();
|
||||
|
||||
bool enableAudio = false;
|
||||
|
||||
int argIndex = 1;
|
||||
while (argIndex < argc) {
|
||||
if (argv[argIndex] == std::string_view("--mount") ||
|
||||
|
|
@ -575,7 +573,7 @@ int main(int argc, const char *argv[]) {
|
|||
if (argv[argIndex] == std::string_view("--enable-audio") ||
|
||||
argv[argIndex] == std::string_view("-a")) {
|
||||
argIndex++;
|
||||
g_enableAudio = true;
|
||||
enableAudio = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -591,6 +589,10 @@ int main(int argc, const char *argv[]) {
|
|||
rx::vm::initialize();
|
||||
runRpsxGpu();
|
||||
|
||||
if (enableAudio) {
|
||||
orbis::g_context.audioOut = orbis::knew<orbis::AudioOut>();
|
||||
}
|
||||
|
||||
// rx::vm::printHostStats();
|
||||
auto initProcess = orbis::g_context.createProcess(10);
|
||||
pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
||||
|
|
|
|||
Loading…
Reference in a new issue