mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
248 lines
10 KiB
C++
248 lines
10 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "common/logging/log.h"
|
|
#include "core/libraries/ajm/ajm.h"
|
|
#include "core/libraries/ajm/ajm_context.h"
|
|
#include "core/libraries/ajm/ajm_error.h"
|
|
#include "core/libraries/ajm/ajm_mp3.h"
|
|
#include "core/libraries/error_codes.h"
|
|
#include "core/libraries/libs.h"
|
|
|
|
#include <magic_enum/magic_enum.hpp>
|
|
|
|
namespace Libraries::Ajm {
|
|
|
|
constexpr int ORBIS_AJM_CHANNELMASK_MONO = 0x0004;
|
|
constexpr int ORBIS_AJM_CHANNELMASK_STEREO = 0x0003;
|
|
constexpr int ORBIS_AJM_CHANNELMASK_QUAD = 0x0033;
|
|
constexpr int ORBIS_AJM_CHANNELMASK_5POINT1 = 0x060F;
|
|
constexpr int ORBIS_AJM_CHANNELMASK_7POINT1 = 0x063F;
|
|
|
|
static std::unordered_map<u32, std::unique_ptr<AjmContext>> contexts{};
|
|
|
|
u32 GetChannelMask(u32 num_channels) {
|
|
switch (num_channels) {
|
|
case 1:
|
|
return ORBIS_AJM_CHANNELMASK_MONO;
|
|
case 2:
|
|
return ORBIS_AJM_CHANNELMASK_STEREO;
|
|
case 4:
|
|
return ORBIS_AJM_CHANNELMASK_QUAD;
|
|
case 6:
|
|
return ORBIS_AJM_CHANNELMASK_5POINT1;
|
|
case 8:
|
|
return ORBIS_AJM_CHANNELMASK_7POINT1;
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmBatchCancel(const u32 context_id, const u32 batch_id) {
|
|
LOG_INFO(Lib_Ajm, "called context_id = {} batch_id = {}", context_id, batch_id);
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->BatchCancel(batch_id);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmBatchErrorDump() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(void* p_buffer, u32 instance_id, u64 flags,
|
|
void* p_sideband_input, size_t sideband_input_size,
|
|
void* p_sideband_output,
|
|
size_t sideband_output_size,
|
|
void* p_return_address) {
|
|
return BatchJobControlBufferRa(p_buffer, instance_id, flags, p_sideband_input,
|
|
sideband_input_size, p_sideband_output, sideband_output_size,
|
|
p_return_address);
|
|
}
|
|
|
|
void* PS4_SYSV_ABI sceAjmBatchJobInlineBuffer(void* p_buffer, const void* p_data_input,
|
|
size_t data_input_size,
|
|
const void** pp_batch_address) {
|
|
return BatchJobInlineBuffer(p_buffer, p_data_input, data_input_size, pp_batch_address);
|
|
}
|
|
|
|
void* PS4_SYSV_ABI sceAjmBatchJobRunBufferRa(void* p_buffer, u32 instance_id, u64 flags,
|
|
void* p_data_input, size_t data_input_size,
|
|
void* p_data_output, size_t data_output_size,
|
|
void* p_sideband_output, size_t sideband_output_size,
|
|
void* p_return_address) {
|
|
return BatchJobRunBufferRa(p_buffer, instance_id, flags, p_data_input, data_input_size,
|
|
p_data_output, data_output_size, p_sideband_output,
|
|
sideband_output_size, p_return_address);
|
|
}
|
|
|
|
void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(
|
|
void* p_buffer, u32 instance_id, u64 flags, const AjmBuffer* p_data_input_buffers,
|
|
size_t num_data_input_buffers, const AjmBuffer* p_data_output_buffers,
|
|
size_t num_data_output_buffers, void* p_sideband_output, size_t sideband_output_size,
|
|
void* p_return_address) {
|
|
return BatchJobRunSplitBufferRa(p_buffer, instance_id, flags, p_data_input_buffers,
|
|
num_data_input_buffers, p_data_output_buffers,
|
|
num_data_output_buffers, p_sideband_output,
|
|
sideband_output_size, p_return_address);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context_id, u8* p_batch, u32 batch_size,
|
|
const int priority, AjmBatchError* batch_error,
|
|
u32* out_batch_id) {
|
|
LOG_TRACE(Lib_Ajm, "called context = {}, batch_size = {:#x}, priority = {}", context_id,
|
|
batch_size, priority);
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->BatchStartBuffer(p_batch, batch_size, priority, batch_error, out_batch_id);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmBatchWait(const u32 context_id, const u32 batch_id, const u32 timeout,
|
|
AjmBatchError* const batch_error) {
|
|
LOG_TRACE(Lib_Ajm, "called context = {}, batch_id = {}, timeout = {}", context_id, batch_id,
|
|
timeout);
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->BatchWait(batch_id, timeout, batch_error);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmDecAt9ParseConfigData() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmDecMp3ParseFrame(const u8* buf, u32 stream_size, int parse_ofl,
|
|
AjmDecMp3ParseFrame* frame) {
|
|
return AjmMp3Decoder::ParseMp3Header(buf, stream_size, parse_ofl, frame);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmFinalize() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInitialize(s64 reserved, u32* p_context_id) {
|
|
LOG_INFO(Lib_Ajm, "called reserved = {}", reserved);
|
|
if (p_context_id == nullptr || reserved != 0) {
|
|
return ORBIS_AJM_ERROR_INVALID_PARAMETER;
|
|
}
|
|
u32 id = contexts.size() + 1;
|
|
*p_context_id = id;
|
|
contexts.emplace(id, std::make_unique<AjmContext>());
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInstanceCodecType() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context_id, AjmCodecType codec_type,
|
|
AjmInstanceFlags flags, u32* out_instance) {
|
|
LOG_INFO(Lib_Ajm, "called context = {}, codec_type = {}, flags = {:#x}", context_id,
|
|
magic_enum::enum_name(codec_type), flags.raw);
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->InstanceCreate(codec_type, flags, out_instance);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context_id, u32 instance_id) {
|
|
LOG_INFO(Lib_Ajm, "called context = {}, instance = {}", context_id, instance_id);
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->InstanceDestroy(instance_id);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInstanceExtend() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmInstanceSwitch() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmMemoryRegister(u32 context_id, void* ptr, size_t num_pages) {
|
|
// All memory is already shared with our implementation since we do not use any hardware.
|
|
LOG_TRACE(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmMemoryUnregister(u32 context_id, void* ptr) {
|
|
// All memory is already shared with our implementation since we do not use any hardware.
|
|
LOG_TRACE(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmModuleRegister(u32 context_id, AjmCodecType codec_type, s64 reserved) {
|
|
LOG_INFO(Lib_Ajm, "called context = {}, codec_type = {}", context_id, u32(codec_type));
|
|
if (reserved != 0) {
|
|
return ORBIS_AJM_ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
auto it = contexts.find(context_id);
|
|
if (it == contexts.end()) {
|
|
return ORBIS_AJM_ERROR_INVALID_CONTEXT;
|
|
}
|
|
|
|
return it->second->ModuleRegister(codec_type);
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmModuleUnregister() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI sceAjmStrError() {
|
|
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
|
LIB_FUNCTION("NVDXiUesSbA", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchCancel);
|
|
LIB_FUNCTION("WfAiBW8Wcek", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchErrorDump);
|
|
LIB_FUNCTION("dmDybN--Fn8", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobControlBufferRa);
|
|
LIB_FUNCTION("stlghnic3Jc", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobInlineBuffer);
|
|
LIB_FUNCTION("ElslOCpOIns", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobRunBufferRa);
|
|
LIB_FUNCTION("7jdAXK+2fMo", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobRunSplitBufferRa);
|
|
LIB_FUNCTION("fFFkk0xfGWs", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchStartBuffer);
|
|
LIB_FUNCTION("-qLsfDAywIY", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchWait);
|
|
LIB_FUNCTION("1t3ixYNXyuc", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmDecAt9ParseConfigData);
|
|
LIB_FUNCTION("eDFeTyi+G3Y", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmDecMp3ParseFrame);
|
|
LIB_FUNCTION("MHur6qCsUus", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmFinalize);
|
|
LIB_FUNCTION("dl+4eHSzUu4", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInitialize);
|
|
LIB_FUNCTION("diXjQNiMu-s", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInstanceCodecType);
|
|
LIB_FUNCTION("AxoDrINp4J8", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInstanceCreate);
|
|
LIB_FUNCTION("RbLbuKv8zho", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInstanceDestroy);
|
|
LIB_FUNCTION("YDFR0dDVGAg", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInstanceExtend);
|
|
LIB_FUNCTION("rgLjmfdXocI", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmInstanceSwitch);
|
|
LIB_FUNCTION("bkRHEYG6lEM", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmMemoryRegister);
|
|
LIB_FUNCTION("pIpGiaYkHkM", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmMemoryUnregister);
|
|
LIB_FUNCTION("Q3dyFuwGn64", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmModuleRegister);
|
|
LIB_FUNCTION("Wi7DtlLV+KI", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmModuleUnregister);
|
|
LIB_FUNCTION("AxhcqVv5AYU", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmStrError);
|
|
};
|
|
|
|
} // namespace Libraries::Ajm
|