diff --git a/CMakeLists.txt b/CMakeLists.txt index f41545ccf..bae59b831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index fe4ac5e9e..1c3a14b59 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -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) diff --git a/src/core/libraries/ajm/ajm.cpp b/src/core/libraries/ajm/ajm.cpp index 5de28a801..cb3f0e265 100644 --- a/src/core/libraries/ajm/ajm.cpp +++ b/src/core/libraries/ajm/ajm.cpp @@ -4,7 +4,9 @@ #include #include +#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 #include #include #include #include #include -#include } namespace Libraries::Ajm { @@ -35,7 +37,7 @@ struct AjmDevice { u32 release_cursor{MaxInstances - 1}; std::array is_registered{}; std::array free_instances{}; - std::array, MaxInstances> instances; + std::array, MaxInstances> instances; bool IsRegistered(AjmCodecType type) const { return is_registered[static_cast(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(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(reinterpret_cast(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(job_ptr + 8); + auto* sideband_ptr = *reinterpret_cast(job_ptr + 8); auto* result = reinterpret_cast(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(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(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(); + std::unique_ptr instance; + switch (codec_type) { + case AjmCodecType::Mp3Dec: + instance = std::make_unique(); + break; + case AjmCodecType::At9Dec: + instance = std::make_unique(); + 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; } diff --git a/src/core/libraries/ajm/ajm.h b/src/core/libraries/ajm/ajm.h index c6ab3958c..3fbda7659 100644 --- a/src/core/libraries/ajm/ajm.h +++ b/src/core/libraries/ajm/ajm.h @@ -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(); diff --git a/src/core/libraries/ajm/ajm_at9.cpp b/src/core/libraries/ajm/ajm_at9.cpp new file mode 100644 index 000000000..c1a208881 --- /dev/null +++ b/src/core/libraries/ajm/ajm_at9.cpp @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include "common/assert.h" +#include "core/libraries/ajm/ajm_at9.h" + +extern "C" { +#include +} + +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 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 diff --git a/src/core/libraries/ajm/ajm_at9.h b/src/core/libraries/ajm/ajm_at9.h new file mode 100644 index 000000000..a7760829b --- /dev/null +++ b/src/core/libraries/ajm/ajm_at9.h @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "common/types.h" +#include "core/libraries/ajm/ajm_instance.h" + +extern "C" { +#include +} + +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 Decode(const u8* in_buf, u32 in_size, u8* out_buf, + u32 out_size) override; +}; + +} // namespace Libraries::Ajm diff --git a/src/core/libraries/ajm/ajm_instance.h b/src/core/libraries/ajm/ajm_instance.h index 12e90dd6c..5fafeac80 100644 --- a/src/core/libraries/ajm/ajm_instance.h +++ b/src/core/libraries/ajm/ajm_instance.h @@ -57,6 +57,7 @@ struct AjmInstance { u32 decoded_samples{}; AjmFormatEncoding fmt{}; u32 num_channels{}; + u32 index{}; explicit AjmInstance() = default; virtual ~AjmInstance() = default; diff --git a/src/core/libraries/ajm/ajm_mp3.h b/src/core/libraries/ajm/ajm_mp3.h index b7a36d5c2..7a81abae4 100644 --- a/src/core/libraries/ajm/ajm_mp3.h +++ b/src/core/libraries/ajm/ajm_mp3.h @@ -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(); diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index 5fb075386..2a4ea31a3 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -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() { diff --git a/src/emulator.cpp b/src/emulator.cpp index e631698fb..de74e6f8c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -194,18 +194,19 @@ void Emulator::Run(const std::filesystem::path& file) { } void Emulator::LoadSystemModules(const std::filesystem::path& file) { - constexpr std::array 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 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 found_modules; const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);