mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-22 04:24:44 +00:00
work
This commit is contained in:
parent
1b1ad53792
commit
a805653061
10 changed files with 329 additions and 94 deletions
|
@ -170,6 +170,10 @@ set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
|||
src/core/libraries/audio/audioout.h
|
||||
src/core/libraries/ajm/ajm.cpp
|
||||
src/core/libraries/ajm/ajm.h
|
||||
src/core/libraries/ajm/ajm_mp3.cpp
|
||||
src/core/libraries/ajm/ajm_mp3.h
|
||||
src/core/libraries/ajm/ajm_at9.cpp
|
||||
src/core/libraries/ajm/ajm_at9.h
|
||||
src/core/libraries/ngs2/ngs2.cpp
|
||||
src/core/libraries/ngs2/ngs2.h
|
||||
)
|
||||
|
@ -667,8 +671,6 @@ if (ENABLE_QT_GUI)
|
|||
${VIDEO_CORE}
|
||||
${EMULATOR}
|
||||
src/images/shadPS4.icns
|
||||
src/core/libraries/ajm/ajm_mp3.h src/core/libraries/ajm/ajm_mp3.cpp
|
||||
src/core/libraries/ajm/ajm_instance.h
|
||||
)
|
||||
else()
|
||||
add_executable(shadps4
|
||||
|
@ -690,7 +692,7 @@ endif()
|
|||
|
||||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui libatrac9)
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui LibAtrac9)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3)
|
||||
|
||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||
|
|
9
externals/CMakeLists.txt
vendored
9
externals/CMakeLists.txt
vendored
|
@ -47,6 +47,15 @@ if (NOT TARGET FFmpeg::ffmpeg)
|
|||
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
||||
endif()
|
||||
|
||||
# LibAtrac9
|
||||
|
||||
file(GLOB LIBATRAC9_SOURCES
|
||||
LibAtrac9/C/src/*.c
|
||||
)
|
||||
|
||||
add_library(LibAtrac9 STATIC ${LIBATRAC9_SOURCES})
|
||||
target_include_directories(LibAtrac9 PUBLIC LibAtrac9/C/src)
|
||||
|
||||
# Zlib-Ng
|
||||
if (NOT TARGET zlib-ng::zlib)
|
||||
set(ZLIB_ENABLE_TESTS OFF)
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include <numeric>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
#include "ajm_at9.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/ajm/ajm.h"
|
||||
#include "core/libraries/ajm/ajm_error.h"
|
||||
|
@ -14,12 +16,12 @@
|
|||
#include "core/libraries/libs.h"
|
||||
|
||||
extern "C" {
|
||||
#include <error_codes.h>
|
||||
#include <libatrac9.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include <structures.h>
|
||||
#include <error_codes.h>
|
||||
}
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
@ -35,7 +37,7 @@ struct AjmDevice {
|
|||
u32 release_cursor{MaxInstances - 1};
|
||||
std::array<bool, NumAjmCodecs> is_registered{};
|
||||
std::array<u32, MaxInstances> free_instances{};
|
||||
std::array<std::unique_ptr<AjmInstance>, MaxInstances> instances;
|
||||
std::array<std::unique_ptr<AjmAt9Decoder>, MaxInstances> instances;
|
||||
|
||||
bool IsRegistered(AjmCodecType type) const {
|
||||
return is_registered[static_cast<u32>(type)];
|
||||
|
@ -62,12 +64,15 @@ int PS4_SYSV_ABI sceAjmBatchErrorDump() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
u8* in_buffer, u32 in_size, u8* out_buffer,
|
||||
u32 out_size, const void* ret_addr) {
|
||||
LOG_INFO(Lib_Ajm, "called instance = {:#x}, flags = {:#x}, cmd = {}, in_size = {:#x}, out_size = {:#x}, ret_addr = {}",
|
||||
instance, flags.raw, magic_enum::enum_name(AjmJobControlFlags(flags.command)),
|
||||
in_size, out_size, fmt::ptr(ret_addr));
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 instance,
|
||||
AjmFlags flags, u8* in_buffer, u32 in_size,
|
||||
u8* out_buffer, u32 out_size,
|
||||
const void* ret_addr) {
|
||||
LOG_INFO(Lib_Ajm,
|
||||
"called instance = {:#x}, flags = {:#x}, cmd = {}, in_size = {:#x}, out_size = {:#x}, "
|
||||
"ret_addr = {}",
|
||||
instance, flags.raw, magic_enum::enum_name(AjmJobControlFlags(flags.command)), in_size,
|
||||
out_size, fmt::ptr(ret_addr));
|
||||
|
||||
const u64 mask = instance == AJM_INSTANCE_STATISTICS ? 0xc0018007ULL : 0x60000000e7ffULL;
|
||||
flags.raw &= mask;
|
||||
|
@ -81,6 +86,10 @@ void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 in
|
|||
batch_pos->opcode.is_statistic = instance == AJM_INSTANCE_STATISTICS;
|
||||
batch_pos->opcode.is_control = true;
|
||||
|
||||
if (instance == AJM_INSTANCE_STATISTICS) {
|
||||
BREAKPOINT();
|
||||
}
|
||||
|
||||
AjmInOutJob* job = nullptr;
|
||||
if (ret_addr == nullptr) {
|
||||
batch_pos->job_size = sizeof(AjmInOutJob);
|
||||
|
@ -106,25 +115,104 @@ void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 in
|
|||
return ++job;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmBatchJobInlineBuffer() {
|
||||
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobInlineBuffer(AjmSingleJob* batch_pos, const void* in_buffer,
|
||||
size_t in_size, const void** batch_address) {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmBatchJobRunBufferRa() {
|
||||
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
auto ParseWavHeader = [](void* buf, WavHeader* header) {
|
||||
if (!buf) {
|
||||
// buf is passed as nullptr in some cases (i.e. GetCodecInfo)
|
||||
return;
|
||||
}
|
||||
std::memcpy(header, buf, sizeof(WavHeader));
|
||||
|
||||
std::string riff(header->RIFF, 4);
|
||||
std::string wave(header->WAVE, 4);
|
||||
std::string fmt(header->fmt, 4);
|
||||
std::string dataID(header->Subchunk2ID, 4);
|
||||
|
||||
if (std::memcmp(header->RIFF, "RIFF", 4) != 0 || std::memcmp(header->WAVE, "WAVE", 4) != 0 ||
|
||||
std::memcmp(header->fmt, "fmt ", 4) != 0 ||
|
||||
std::memcmp(header->Subchunk2ID, "data", 4) != 0) {
|
||||
LOG_ERROR(Lib_Ajm, "Invalid WAV file.");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(Lib_Ajm, "RIFF header: {}", riff);
|
||||
LOG_INFO(Lib_Ajm, "WAVE header: {}", wave);
|
||||
LOG_INFO(Lib_Ajm, "FMT: {}", fmt);
|
||||
LOG_INFO(Lib_Ajm, "Data size: {}", header->ChunkSize);
|
||||
LOG_INFO(Lib_Ajm, "Sampling Rate: {}", header->SamplesPerSec);
|
||||
LOG_INFO(Lib_Ajm, "Number of bits used: {}", header->bitsPerSample);
|
||||
LOG_INFO(Lib_Ajm, "Number of channels: {}", header->NumOfChan);
|
||||
LOG_INFO(Lib_Ajm, "Number of bytes per second: {}", header->bytesPerSec);
|
||||
LOG_INFO(Lib_Ajm, "Data length: {}", header->Subchunk2Size);
|
||||
LOG_INFO(Lib_Ajm, "Audio Format: {}", header->AudioFormat);
|
||||
LOG_INFO(Lib_Ajm, "Block align: {}", header->blockAlign);
|
||||
LOG_INFO(Lib_Ajm, "Data string: {}", dataID);
|
||||
};
|
||||
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunBufferRa(AjmSingleJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
void* in_buffer, u32 in_size, u8* out_buffer,
|
||||
const u32 out_size, u8* sideband_output,
|
||||
const u32 sideband_output_size, const void* ret_addr) {
|
||||
WavHeader header{};
|
||||
ParseWavHeader(in_buffer, &header);
|
||||
LOG_INFO(Lib_Ajm,
|
||||
"called instance = {:#x}, flags = {:#x}, cmd = {}, in_size = {:#x}, out_size = {:#x}, "
|
||||
"ret_addr = {}",
|
||||
instance, flags.raw, magic_enum::enum_name(AjmJobRunFlags(flags.command)), in_size,
|
||||
out_size, fmt::ptr(ret_addr));
|
||||
|
||||
const u64 mask = 0xE00000001FFFLL;
|
||||
flags.raw &= mask;
|
||||
|
||||
const bool is_debug = ret_addr != nullptr;
|
||||
batch_pos->opcode.instance = instance;
|
||||
batch_pos->opcode.codec_flags = flags.codec;
|
||||
batch_pos->opcode.command_flags = flags.command;
|
||||
batch_pos->opcode.sideband_flags = AjmJobSidebandFlags(flags.sideband);
|
||||
batch_pos->opcode.is_debug = is_debug;
|
||||
batch_pos->opcode.is_statistic = false;
|
||||
batch_pos->opcode.is_control = false;
|
||||
|
||||
AjmInOutJob* job = nullptr;
|
||||
if (ret_addr == nullptr) {
|
||||
batch_pos->job_size = sizeof(AjmInOutJob) + 16;
|
||||
job = &batch_pos->job;
|
||||
} else {
|
||||
batch_pos->job_size = sizeof(AjmInOutJob) + 32;
|
||||
batch_pos->ret.unk1 = batch_pos->ret.unk1 & 0xfffffff0 | 6;
|
||||
job = &batch_pos->ret.job;
|
||||
}
|
||||
|
||||
// todo: add some missing stuff
|
||||
job->input.buf_size = in_size;
|
||||
job->input.buffer = static_cast<u8*>(in_buffer);
|
||||
job->flags = u32(flags.raw);
|
||||
job->unk1 = (job->unk1 & 0xfc000030) + (flags.raw >> 0x1a) + 4;
|
||||
job->output.buf_size = out_size;
|
||||
job->output.buffer = out_buffer;
|
||||
job->output.props &= 0xffffffe0;
|
||||
job->output.props |= 0x12;
|
||||
*reinterpret_cast<u8**>(reinterpret_cast<u8*>(job) + 32) = sideband_output;
|
||||
return job;
|
||||
}
|
||||
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(AjmMultiJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
const AjmBuffer* in_buffers, u64 num_in_buffers,
|
||||
const AjmBuffer* out_buffers, u64 num_out_buffers,
|
||||
void* sideband_output, u64 sideband_output_size,
|
||||
const void* ret_addr) {
|
||||
LOG_DEBUG(Lib_Ajm, "called instance = {}, flags = {:#x}, cmd = {}, sideband_cmd = {} num_input_buffers = {}, num_output_buffers = {}, "
|
||||
"ret_addr = {}", instance, flags.raw, magic_enum::enum_name(AjmJobRunFlags(flags.command)),
|
||||
magic_enum::enum_name(AjmJobSidebandFlags(flags.sideband)),
|
||||
num_in_buffers, num_out_buffers, fmt::ptr(ret_addr));
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(AjmMultiJob* batch_pos, u32 instance,
|
||||
AjmFlags flags, const AjmBuffer* in_buffers,
|
||||
u64 num_in_buffers, const AjmBuffer* out_buffers,
|
||||
u64 num_out_buffers, void* sideband_output,
|
||||
u64 sideband_output_size, const void* ret_addr) {
|
||||
LOG_DEBUG(Lib_Ajm,
|
||||
"called instance = {}, flags = {:#x}, cmd = {}, sideband_cmd = {} num_input_buffers "
|
||||
"= {}, num_output_buffers = {}, "
|
||||
"ret_addr = {}",
|
||||
instance, flags.raw, magic_enum::enum_name(AjmJobRunFlags(flags.command)),
|
||||
magic_enum::enum_name(AjmJobSidebandFlags(flags.sideband)), num_in_buffers,
|
||||
num_out_buffers, fmt::ptr(ret_addr));
|
||||
const u32 job_size = (num_in_buffers * 2 + 1 + num_out_buffers * 2) * 8;
|
||||
const bool is_debug = ret_addr != nullptr;
|
||||
batch_pos->opcode.instance = instance;
|
||||
|
@ -169,16 +257,17 @@ void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(AjmMultiJob* batch_pos, u32 in
|
|||
out_buf->buffer = out_buffers[i].addr;
|
||||
job += 4;
|
||||
}
|
||||
job[0] = job[0] & 0xffffffe0 | 0x12;
|
||||
job[1] = sideband_output_size;
|
||||
memcpy(&job[2], &sideband_output, sizeof(void*));
|
||||
job[0] = job[0] & 0xffffffe0 | 0x12; // output.props
|
||||
job[1] = sideband_output_size; // output.buf_size
|
||||
memcpy(&job[2], &sideband_output, sizeof(void*)); // output.buffer
|
||||
return job + 4;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_size, const int priority,
|
||||
AjmBatchError* patch_error, u32* out_batch_id) {
|
||||
LOG_DEBUG(Lib_Ajm, "called context = {}, batch_size = {:#x}, priority = {}",
|
||||
context, batch_size, priority);
|
||||
int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_size,
|
||||
const int priority, AjmBatchError* batch_error,
|
||||
u32* out_batch_id) {
|
||||
LOG_DEBUG(Lib_Ajm, "called context = {}, batch_size = {:#x}, priority = {}", context,
|
||||
batch_size, priority);
|
||||
|
||||
if ((batch_size & 7) != 0) {
|
||||
return ORBIS_AJM_ERROR_MALFORMED_BATCH;
|
||||
|
@ -208,7 +297,7 @@ int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_
|
|||
const u8* job_ptr = batch_ptr + sizeof(AjmJobHeader) + opcode.is_debug * 16;
|
||||
|
||||
if (opcode.is_control) {
|
||||
ASSERT_MSG(!opcode.is_statistic, "Statistic instance is not handled");
|
||||
// ASSERT_MSG(!opcode.is_statistic, "Statistic instance is not handled");
|
||||
const auto command = AjmJobControlFlags(opcode.command_flags);
|
||||
switch (command) {
|
||||
case AjmJobControlFlags::Reset: {
|
||||
|
@ -243,13 +332,12 @@ int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_
|
|||
fmt::ptr(in_buffer->buffer), in_buffer->buf_size);
|
||||
|
||||
// Decode as much of the input bitstream as possible.
|
||||
auto* instance = dev->instances[opcode.instance].get();
|
||||
const auto [in_remain, out_remain, num_frames] =
|
||||
instance->Decode(in_buffer->buffer, in_buffer->buf_size,
|
||||
out_buffer->buffer, out_buffer->buf_size);
|
||||
AjmAt9Decoder* decoder_instance = dev->instances[opcode.instance].get();
|
||||
const auto [in_remain, out_remain, num_frames] = decoder_instance->Decode(
|
||||
in_buffer->buffer, in_buffer->buf_size, out_buffer->buffer, out_buffer->buf_size);
|
||||
|
||||
// Write sideband structures.
|
||||
auto* sideband_ptr = *reinterpret_cast<u8* const *>(job_ptr + 8);
|
||||
auto* sideband_ptr = *reinterpret_cast<u8* const*>(job_ptr + 8);
|
||||
auto* result = reinterpret_cast<AjmSidebandResult*>(sideband_ptr);
|
||||
result->result = 0;
|
||||
result->internal_result = 0;
|
||||
|
@ -260,7 +348,7 @@ int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_
|
|||
auto* stream = reinterpret_cast<AjmSidebandStream*>(sideband_ptr);
|
||||
stream->input_consumed = in_buffer->buf_size - in_remain;
|
||||
stream->output_written = out_buffer->buf_size - out_remain;
|
||||
stream->total_decoded_samples = instance->decoded_samples;
|
||||
stream->total_decoded_samples = decoder_instance->decoded_samples;
|
||||
sideband_ptr += sizeof(AjmSidebandStream);
|
||||
}
|
||||
if (True(command & AjmJobRunFlags::MultipleFrames)) {
|
||||
|
@ -268,6 +356,15 @@ int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_
|
|||
mframe->num_frames = num_frames;
|
||||
sideband_ptr += sizeof(AjmSidebandMFrame);
|
||||
}
|
||||
if (True(command & AjmJobRunFlags::GetCodecInfo)) {
|
||||
LOG_TRACE(Lib_Ajm, "GetCodecInfo called, supplying dummy info for now");
|
||||
auto* codec_info = reinterpret_cast<SceAjmSidebandDecAt9CodecInfo*>(sideband_ptr);
|
||||
codec_info->uiFrameSamples = 0;
|
||||
codec_info->uiFramesInSuperFrame = 0;
|
||||
codec_info->uiNextFrameSize = 0;
|
||||
codec_info->uiSuperFrameSize = 0;
|
||||
sideband_ptr += sizeof(SceAjmSidebandDecAt9CodecInfo);
|
||||
}
|
||||
}
|
||||
|
||||
batch_ptr += sizeof(AjmJobHeader) + header.job_size;
|
||||
|
@ -336,7 +433,17 @@ int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmI
|
|||
}
|
||||
const u32 index = dev->free_instances[dev->curr_cursor++];
|
||||
dev->curr_cursor %= MaxInstances;
|
||||
auto instance = std::make_unique<AjmMp3Decoder>();
|
||||
std::unique_ptr<AjmAt9Decoder> instance;
|
||||
switch (codec_type) {
|
||||
case AjmCodecType::Mp3Dec:
|
||||
instance = std::make_unique<AjmAt9Decoder>();
|
||||
break;
|
||||
case AjmCodecType::At9Dec:
|
||||
instance = std::make_unique<AjmAt9Decoder>();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
instance->index = index;
|
||||
instance->codec_type = codec_type;
|
||||
instance->num_channels = flags.channels;
|
||||
|
@ -383,7 +490,8 @@ int PS4_SYSV_ABI sceAjmMemoryUnregister() {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAjmModuleRegister(u32 context, AjmCodecType codec_type, s64 reserved) {
|
||||
LOG_INFO(Lib_Ajm, "called context = {}, codec_type = {}, reserved = {}", context, u32(codec_type), reserved);
|
||||
LOG_INFO(Lib_Ajm, "called context = {}, codec_type = {}, reserved = {}", context,
|
||||
u32(codec_type), reserved);
|
||||
if (codec_type >= AjmCodecType::Max || reserved != 0) {
|
||||
return ORBIS_AJM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include "common/enum.h"
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
|
@ -92,6 +92,8 @@ struct AjmSingleJob {
|
|||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(AjmSingleJob) == 0x40);
|
||||
|
||||
struct AjmMultiJob {
|
||||
AjmHLEOpcode opcode;
|
||||
u32 job_size;
|
||||
|
@ -128,26 +130,37 @@ union AjmInstanceFlags {
|
|||
};
|
||||
};
|
||||
|
||||
struct SceAjmSidebandDecAt9CodecInfo {
|
||||
u32 uiSuperFrameSize;
|
||||
u32 uiFramesInSuperFrame;
|
||||
u32 uiNextFrameSize;
|
||||
u32 uiFrameSamples;
|
||||
};
|
||||
|
||||
struct AjmDecMp3ParseFrame;
|
||||
enum class AjmCodecType : u32;
|
||||
|
||||
int PS4_SYSV_ABI sceAjmBatchCancel();
|
||||
int PS4_SYSV_ABI sceAjmBatchErrorDump();
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
u8* in_buffer, u32 in_size, u8* out_buffer,
|
||||
u32 out_size, const void* ret_addr);
|
||||
int PS4_SYSV_ABI sceAjmBatchJobInlineBuffer();
|
||||
int PS4_SYSV_ABI sceAjmBatchJobRunBufferRa();
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(AjmMultiJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
const AjmBuffer* input_buffers,
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobControlBufferRa(AjmSingleJob* batch_pos, u32 instance,
|
||||
AjmFlags flags, u8* in_buffer, u32 in_size,
|
||||
u8* out_buffer, u32 out_size,
|
||||
const void* ret_addr);
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobInlineBuffer(AjmSingleJob* batch_pos, const void* in_buffer,
|
||||
size_t in_size, const void** batch_address);
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunBufferRa(AjmSingleJob* batch_pos, u32 instance, AjmFlags flags,
|
||||
void * in_buffer, u32 in_size, u8* out_buffer,
|
||||
const u32 out_size, u8* sideband_output,
|
||||
const u32 sideband_output_size, const void* ret_addr);
|
||||
void* PS4_SYSV_ABI sceAjmBatchJobRunSplitBufferRa(AjmMultiJob* batch_pos, u32 instance,
|
||||
AjmFlags flags, const AjmBuffer* input_buffers,
|
||||
u64 num_input_buffers,
|
||||
const AjmBuffer* output_buffers,
|
||||
u64 num_output_buffers,
|
||||
void* sideband_output,
|
||||
u64 sideband_output_size,
|
||||
const void* ret_addr);
|
||||
int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_size, const int priority,
|
||||
AjmBatchError* patch_error, u32* out_batch_id);
|
||||
u64 num_output_buffers, void* sideband_output,
|
||||
u64 sideband_output_size, const void* ret_addr);
|
||||
int PS4_SYSV_ABI sceAjmBatchStartBuffer(u32 context, const u8* batch, u32 batch_size,
|
||||
const int priority, AjmBatchError* patch_error,
|
||||
u32* out_batch_id);
|
||||
int PS4_SYSV_ABI sceAjmBatchWait();
|
||||
int PS4_SYSV_ABI sceAjmDecAt9ParseConfigData();
|
||||
int PS4_SYSV_ABI sceAjmDecMp3ParseFrame(const u8* stream, u32 stream_size, int parse_ofl,
|
||||
|
@ -155,7 +168,8 @@ int PS4_SYSV_ABI sceAjmDecMp3ParseFrame(const u8* stream, u32 stream_size, int p
|
|||
int PS4_SYSV_ABI sceAjmFinalize();
|
||||
int PS4_SYSV_ABI sceAjmInitialize(s64 reserved, u32* out_context);
|
||||
int PS4_SYSV_ABI sceAjmInstanceCodecType();
|
||||
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmInstanceFlags flags, u32* instance);
|
||||
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmInstanceFlags flags,
|
||||
u32* instance);
|
||||
int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context, u32 instance);
|
||||
int PS4_SYSV_ABI sceAjmInstanceExtend();
|
||||
int PS4_SYSV_ABI sceAjmInstanceSwitch();
|
||||
|
|
58
src/core/libraries/ajm/ajm_at9.cpp
Normal file
58
src/core/libraries/ajm/ajm_at9.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/ajm/ajm_at9.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libatrac9.h>
|
||||
}
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
||||
AjmAt9Decoder::AjmAt9Decoder() {
|
||||
handle = Atrac9GetHandle();
|
||||
ASSERT_MSG(handle, "Atrac9GetHandle failed");
|
||||
AjmAt9Decoder::Reset();
|
||||
}
|
||||
|
||||
AjmAt9Decoder::~AjmAt9Decoder() {}
|
||||
|
||||
void AjmAt9Decoder::Reset() {
|
||||
decoded_samples = 0;
|
||||
static int filename = 0;
|
||||
file.close();
|
||||
file.open(fmt::format("inst{}_{}.raw", index, ++filename), std::ios::out | std::ios::binary);
|
||||
}
|
||||
|
||||
std::tuple<u32, u32, u32> AjmAt9Decoder::Decode(const u8* in_buf, u32 in_size, u8* out_buf,
|
||||
u32 out_size) {
|
||||
auto ParseWavHeader = [](const uint8_t* buf, WavHeader* header) {
|
||||
std::memcpy(header, buf, sizeof(WavHeader));
|
||||
};
|
||||
|
||||
if (in_size <= 0 || out_size <= 0) {
|
||||
return std::tuple(in_size, out_size, 0);
|
||||
}
|
||||
|
||||
WavHeader header{};
|
||||
ParseWavHeader(in_buf - 0x64, &header);
|
||||
|
||||
if (!decoder_initialized) {
|
||||
Atrac9InitDecoder(handle, header.configData);
|
||||
decoder_initialized = true;
|
||||
}
|
||||
|
||||
// todo: do something with decoded data :p
|
||||
|
||||
int bytes_used;
|
||||
Atrac9Decode(handle, in_buf, nullptr, &bytes_used);
|
||||
|
||||
Atrac9CodecInfo codec_info;
|
||||
Atrac9GetCodecInfo(handle, &codec_info);
|
||||
|
||||
return std::tuple(in_size, out_size, 0);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Ajm
|
65
src/core/libraries/ajm/ajm_at9.h
Normal file
65
src/core/libraries/ajm/ajm_at9.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <guiddef.h>
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/ajm/ajm_instance.h"
|
||||
|
||||
extern "C" {
|
||||
#include <structures.h>
|
||||
}
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
||||
constexpr unsigned int SCE_AT9_CONFIG_DATA_SIZE = 4;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct WavHeader {
|
||||
/* RIFF Chunk Descriptor */
|
||||
char RIFF[4]; // RIFF Header Magic header
|
||||
uint32_t ChunkSize; // RIFF Chunk Size
|
||||
char WAVE[4]; // WAVE Header
|
||||
/* "fmt" sub-chunk */
|
||||
char fmt[4]; // FMT header
|
||||
uint32_t Subchunk1Size; // Size of the fmt chunk
|
||||
uint16_t AudioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law,
|
||||
// 259=ADPCM
|
||||
uint16_t NumOfChan; // Number of channels 1=Mono 2=Sterio
|
||||
uint32_t SamplesPerSec; // Sampling Frequency in Hz
|
||||
uint32_t bytesPerSec; // bytes per second
|
||||
uint16_t blockAlign; // 2=16-bit mono, 4=16-bit stereo
|
||||
uint16_t bitsPerSample; // Number of bits per sample
|
||||
u16 cbSize; // Extension size
|
||||
u16 samplesPerBlock;
|
||||
u32 channelMask;
|
||||
GUID subFormat;
|
||||
u32 versionInfo;
|
||||
u8 configData[SCE_AT9_CONFIG_DATA_SIZE]; // the juicy part
|
||||
u32 reserved;
|
||||
/* "fact" sub-chunk */
|
||||
char Subchunk2ID[4]; // "fact" string
|
||||
uint32_t Subchunk2Size; // Sampled data length
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(WavHeader) == 80);
|
||||
|
||||
struct AjmAt9Decoder final : AjmInstance {
|
||||
void* handle;
|
||||
bool decoder_initialized = false;
|
||||
std::fstream file;
|
||||
int length;
|
||||
|
||||
explicit AjmAt9Decoder();
|
||||
~AjmAt9Decoder() override;
|
||||
|
||||
void Reset() override;
|
||||
|
||||
std::tuple<u32, u32, u32> Decode(const u8* in_buf, u32 in_size, u8* out_buf,
|
||||
u32 out_size) override;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Ajm
|
|
@ -57,6 +57,7 @@ struct AjmInstance {
|
|||
u32 decoded_samples{};
|
||||
AjmFormatEncoding fmt{};
|
||||
u32 num_channels{};
|
||||
u32 index{};
|
||||
|
||||
explicit AjmInstance() = default;
|
||||
virtual ~AjmInstance() = default;
|
||||
|
|
|
@ -66,7 +66,6 @@ struct AjmMp3Decoder : public AjmInstance {
|
|||
const AVCodec* codec = nullptr;
|
||||
AVCodecContext* c = nullptr;
|
||||
AVCodecParserContext* parser = nullptr;
|
||||
u32 index;
|
||||
std::ofstream file;
|
||||
|
||||
explicit AjmMp3Decoder();
|
||||
|
|
|
@ -1113,30 +1113,8 @@ int PS4_SYSV_ABI sceGnmInsertSetColorMarker() {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmInsertSetMarker(u32 *param_1,int param_2,char *param_3) {
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
u32 uVar3;
|
||||
size_t sVar4;
|
||||
u32 uVar5;
|
||||
u64 uVar6;
|
||||
|
||||
uVar6 = 0xffffffff;
|
||||
if ((param_1 != (u32 *)0x0) && (param_3 != (char *)0x0)) {
|
||||
sVar4 = strlen(param_3);
|
||||
iVar2 = (int)sVar4;
|
||||
uVar3 = (iVar2 + 0xcU) >> 3;
|
||||
uVar5 = (iVar2 + 8U) >> 2;
|
||||
if (uVar5 + 2 + uVar3 * 2 == param_2) {
|
||||
iVar1 = uVar5 + uVar3 * 2;
|
||||
uVar3 = iVar2 + 1;
|
||||
*param_1 = iVar1 * 0x10000 | 0xc0001000;
|
||||
param_1[1] = 0x68750003;
|
||||
memcpy(param_1 + 2,param_3,(ulong)uVar3);
|
||||
uVar6 = 0;
|
||||
memset((void *)((long)(param_1 + 2) + (ulong)uVar3),0,(ulong)(iVar1 * 4 - uVar3));
|
||||
}
|
||||
}
|
||||
return uVar6;
|
||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmInsertThreadTraceMarker() {
|
||||
|
|
|
@ -194,18 +194,19 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||
}
|
||||
|
||||
void Emulator::LoadSystemModules(const std::filesystem::path& file) {
|
||||
constexpr std::array<SysModules, 10> ModulesToLoad{
|
||||
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||
{"libSceFiber.sprx", nullptr},
|
||||
{"libSceUlt.sprx", nullptr},
|
||||
{"libSceJson.sprx", nullptr},
|
||||
{"libSceJson2.sprx", nullptr},
|
||||
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
||||
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||
{"libSceJpegEnc.sprx", nullptr},
|
||||
{"libSceFont.sprx", nullptr}},
|
||||
};
|
||||
constexpr std::array<SysModules, 16> ModulesToLoad{{
|
||||
{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||
{"libSceFiber.sprx", nullptr},
|
||||
{"libSceUlt.sprx", nullptr},
|
||||
{"libSceJson.sprx", nullptr},
|
||||
{"libSceJson2.sprx", nullptr},
|
||||
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
||||
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||
{"libSceJpegEnc.sprx", nullptr},
|
||||
{"libSceFont.sprx", nullptr},
|
||||
{"libSceRazorCpu.sprx", nullptr},
|
||||
}};
|
||||
|
||||
std::vector<std::filesystem::path> found_modules;
|
||||
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
|
|
Loading…
Add table
Reference in a new issue