From 09a4d14f8f34c5623c3e9bbb692fc9f872b99862 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 28 Oct 2014 00:24:11 +0300 Subject: [PATCH] cellAdec improved --- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 261 +++++++++++------------ rpcs3/Emu/SysCalls/Modules/cellAdec.h | 58 +++-- rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp | 149 +++++++++++-- rpcs3/Emu/SysCalls/Modules/cellAtrac.h | 30 ++- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 5 - 7 files changed, 314 insertions(+), 193 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7bfc5daa6c..c3e0f4ff95 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2266,7 +2266,7 @@ void RSXThread::Task() if(cmd == 0) { LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get)); - //Emu.Pause(); + Emu.Pause(); //HACK! We shouldn't be here m_ctrl->get = get + (count + 1) * 4; continue; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 28605b2ee7..972eb1c593 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -52,7 +52,7 @@ AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptrpb = avio_alloc_context(io_buf, 4096, 0, this, adecRead, NULL, NULL); + fmt->pb = avio_alloc_context(io_buf, 256, 0, this, adecRead, NULL, NULL); if (!fmt->pb) { cellAdec->Error("AudioDecoder(): avio_alloc_context failed"); @@ -86,13 +86,44 @@ AudioDecoder::~AudioDecoder() } } -int adecRawRead(void* opaque, u8* buf, int buf_size) +int adecRead(void* opaque, u8* buf, int buf_size) { AudioDecoder& adec = *(AudioDecoder*)opaque; int res = 0; next: + if (adec.reader.has_ats) + { + u8 code1 = vm::read8(adec.reader.addr + 2); + u8 code2 = vm::read8(adec.reader.addr + 3); + adec.channels = code1 >> 2; + adec.frame_size = ((((u32)code1 & 0x3) << 8) | (u32)code2) * 8 + 8; + adec.sample_rate = at3freq[code1 >> 5]; + + adec.reader.size -= 8; + adec.reader.addr += 8; + adec.reader.has_ats = false; + } + + if (!adec.reader.init) + { + OMAHeader oma(1 /* atrac3p id */, adec.sample_rate, adec.channels, adec.frame_size); + if (buf_size < sizeof(oma)) + { + cellAdec->Error("adecRead(): OMAHeader writing failed"); + Emu.Pause(); + return 0; + } + + memcpy(buf, &oma, sizeof(oma)); + buf += sizeof(oma); + buf_size -= sizeof(oma); + res += sizeof(oma); + + adec.reader.init = true; + } + if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/) { AdecTask task; @@ -125,6 +156,7 @@ next: adec.reader.addr = adec.task.au.addr; adec.reader.size = adec.task.au.size; + adec.reader.has_ats = adec.use_ats_headers; //LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts); } break; @@ -158,89 +190,6 @@ next: } } -int adecRead(void* opaque, u8* buf, int buf_size) -{ - AudioDecoder& adec = *(AudioDecoder*)opaque; - - int res = 0; - - if (adec.reader.rem_size && adec.reader.rem) - { - if (buf_size < (int)adec.reader.rem_size) - { - cellAdec->Error("adecRead(): too small buf_size (rem_size = %d, buf_size = %d)", adec.reader.rem_size, buf_size); - Emu.Pause(); - return 0; - } - - memcpy(buf, adec.reader.rem, adec.reader.rem_size); - free(adec.reader.rem); - adec.reader.rem = nullptr; - buf += adec.reader.rem_size; - buf_size -= adec.reader.rem_size; - res += adec.reader.rem_size; - adec.reader.rem_size = 0; - } - - while (buf_size) - { - u8 header[8]; - if (adecRawRead(opaque, header, 8) < 8) break; - if (header[0] != 0x0f || header[1] != 0xd0) - { - cellAdec->Error("adecRead(): 0x0FD0 header not found"); - Emu.Pause(); - return -1; - } - - if (!adec.reader.init) - { - OMAHeader oma(1 /* atrac3p id */, header[2], header[3]); - if (buf_size < sizeof(oma) + 8) - { - cellAdec->Error("adecRead(): OMAHeader writing failed"); - Emu.Pause(); - return 0; - } - - memcpy(buf, &oma, sizeof(oma)); - buf += sizeof(oma); - buf_size -= sizeof(oma); - res += sizeof(oma); - - adec.reader.init = true; - } - else - { - } - - u32 size = (((header[2] & 0x3) << 8) | header[3]) * 8 + 8; // data to be read before next header - - //LOG_NOTICE(HLE, "*** audio block read: size = 0x%x", size); - - if (buf_size < (int)size) - { - if (adecRawRead(opaque, buf, buf_size) < buf_size) break; // ??? - res += buf_size; - size -= buf_size; - buf_size = 0; - - adec.reader.rem = (u8*)malloc(size); - adec.reader.rem_size = size; - if (adecRawRead(opaque, adec.reader.rem, size) < (int)size) break; // ??? - } - else - { - if (adecRawRead(opaque, buf, size) < (int)size) break; // ??? - buf += size; - buf_size -= size; - res += size; - } - } - - return res; -} - u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; @@ -292,10 +241,13 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = 0; adec.reader.size = 0; adec.reader.init = false; - if (adec.reader.rem) free(adec.reader.rem); - adec.reader.rem = nullptr; - adec.reader.rem_size = 0; + adec.reader.has_ats = false; adec.just_started = true; + + adec.channels = task.at3p.channels; + adec.frame_size = task.at3p.frame_size; + adec.sample_rate = task.at3p.sample_rate; + adec.use_ats_headers = task.at3p.ats_header == 1; } break; @@ -315,12 +267,13 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = task.au.addr; adec.reader.size = task.au.size; + adec.reader.has_ats = adec.use_ats_headers; //LOG_NOTICE(HLE, "Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts); if (adec.just_started) { adec.first_pts = task.au.pts; - adec.last_pts = task.au.pts - 0x10000; // hack + adec.last_pts = task.au.pts - 0x10000; // hack? } struct AVPacketHolder : AVPacket @@ -344,36 +297,30 @@ u32 adecOpen(AudioDecoder* data) ~AVPacketHolder() { av_free(data); - //av_free_packet(this); } } au(0); - /*{ - wxFile dump; - dump.Open(wxString::Format("audio pts-0x%llx.dump", task.au.pts), wxFile::write); - u8* buf = (u8*)malloc(task.au.size); - if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); - free(buf); - dump.Close(); - }*/ - if (adec.just_started && adec.just_finished) { avcodec_flush_buffers(adec.ctx); - adec.reader.init = true; + + adec.reader.init = true; // wrong adec.just_finished = false; adec.just_started = false; } else if (adec.just_started) // deferred initialization { - err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL); - if (err) + AVDictionary* opts = nullptr; + av_dict_set(&opts, "probesize", "96", 0); + err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), &opts); + if (err || opts) { - cellAdec->Error("adecDecodeAu: avformat_open_input() failed"); + cellAdec->Error("adecDecodeAu: avformat_open_input() failed (err=0x%x, opts=%d)", err, opts ? 1 : 0); Emu.Pause(); break; } + AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ??? if (!codec) { @@ -402,14 +349,14 @@ u32 adecOpen(AudioDecoder* data) } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data - AVDictionary* opts = nullptr; + opts = nullptr; av_dict_set(&opts, "refcounted_frames", "1", 0); { std::lock_guard lock(g_mutex_avcodec_open2); // not multithread-safe (???) err = avcodec_open2(adec.ctx, codec, &opts); } - if (err) + if (err || opts) { cellAdec->Error("adecDecodeAu: avcodec_open2() failed"); Emu.Pause(); @@ -428,22 +375,6 @@ u32 adecOpen(AudioDecoder* data) break; } - /*if (!adec.ctx) // fake - { - AdecFrame frame; - frame.pts = task.au.pts; - frame.auAddr = task.au.addr; - frame.auSize = task.au.size; - frame.userdata = task.au.userdata; - frame.size = 4096; - frame.data = nullptr; - adec.frames.Push(frame); - - adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - - break; - }*/ - last_frame = av_read_frame(adec.fmt, &au) < 0; if (last_frame) { @@ -501,7 +432,7 @@ u32 adecOpen(AudioDecoder* data) } else { - adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; + adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / frame.data->sample_rate; frame.pts = adec.last_pts; } //frame.pts = adec.last_pts; @@ -517,12 +448,6 @@ u32 adecOpen(AudioDecoder* data) Emu.Pause(); break; } - if (frame.data->channels != 2) - { - cellAdec->Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels); - Emu.Pause(); - break; - } //LOG_NOTICE(HLE, "got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)", //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, @@ -596,7 +521,7 @@ int cellAdecQueryAttr(vm::ptr type, vm::ptr attr) // TODO: check values attr->adecVerLower = 0x280000; // from dmux attr->adecVerUpper = 0x260000; - attr->workMemSize = 4 * 1024 * 1024; // 4 MB + attr->workMemSize = 256 * 1024; // 256 KB return CELL_OK; } @@ -655,7 +580,7 @@ int cellAdecClose(u32 handle) int cellAdecStartSeq(u32 handle, u32 param_addr) { - cellAdec->Todo("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); + cellAdec->Warning("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); AudioDecoder* adec; if (!Emu.GetIdManager().GetIDData(handle, adec)) @@ -665,7 +590,31 @@ int cellAdecStartSeq(u32 handle, u32 param_addr) AdecTask task(adecStartSeq); - // TODO: using parameters + switch (adec->type) + { + case CELL_ADEC_TYPE_ATRACX_2CH: + { + auto param = vm::ptr::make(param_addr); + + task.at3p.sample_rate = param->sampling_freq; + task.at3p.channel_config = param->ch_config_idx; + task.at3p.channels = param->nch_out; + task.at3p.frame_size = param->nbytes; + task.at3p.extra_config = param->extra_config_data; + task.at3p.output = param->bw_pcm; + task.at3p.downmix = param->downmix_flag; + task.at3p.ats_header = param->au_includes_ats_hdr_flg; + cellAdec->Todo("*** CellAdecParamAtracX: sr=%d, ch_cfg=%d(%d), frame_size=0x%x, extra=0x%x, output=%d, downmix=%d, ats_header=%d", + task.at3p.sample_rate, task.at3p.channel_config, task.at3p.channels, task.at3p.frame_size, (u32&)task.at3p.extra_config, task.at3p.output, task.at3p.downmix, task.at3p.ats_header); + break; + } + default: + { + cellAdec->Todo("cellAdecStartSeq(): Unimplemented audio codec type(%d)", adec->type); + Emu.Pause(); + return CELL_OK; + } + } adec->job.Push(task, &adec->is_closed); return CELL_OK; @@ -702,6 +651,7 @@ int cellAdecDecodeAu(u32 handle, vm::ptr auInfo) task.au.pts = ((u64)auInfo->pts.upper << 32) | (u64)auInfo->pts.lower; task.au.userdata = auInfo->userData; + cellAdec->Notice("cellAdecDecodeAu(): addr=0x%x, size=0x%x, pts=0x%llx", task.au.addr, task.au.size, task.au.pts); adec->job.Push(task, &adec->is_closed); return CELL_OK; } @@ -733,14 +683,30 @@ int cellAdecGetPcm(u32 handle, vm::ptr outBuffer) if (outBuffer) { - // reverse byte order, extract data: - float* in_f[2]; - in_f[0] = (float*)frame->extended_data[0]; - in_f[1] = (float*)frame->extended_data[1]; - for (u32 i = 0; i < af.size / 8; i++) + // reverse byte order: + if (frame->channels == 1) { - outBuffer[i * 2 + 0] = in_f[0][i]; - outBuffer[i * 2 + 1] = in_f[1][i]; + float* in_f = (float*)frame->extended_data[0]; + for (u32 i = 0; i < af.size / 4; i++) + { + outBuffer[i] = in_f[i]; + } + } + else if (frame->channels == 2) + { + float* in_f[2]; + in_f[0] = (float*)frame->extended_data[0]; + in_f[1] = (float*)frame->extended_data[1]; + for (u32 i = 0; i < af.size / 8; i++) + { + outBuffer[i * 2 + 0] = in_f[0][i]; + outBuffer[i * 2 + 1] = in_f[1][i]; + } + } + else + { + cellAdec->Error("cellAdecGetPcm(): unsupported channel count (%d)", frame->channels); + Emu.Pause(); } } @@ -788,12 +754,23 @@ int cellAdecGetPcmItem(u32 handle, vm::ptr pcmItem_ptr) pcm->auInfo.userData = af.userdata; auto atx = vm::ptr::make(pcm.addr() + sizeof(CellAdecPcmItem)); - atx->samplingFreq = frame->sample_rate; // ??? - atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ??? - atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? + atx->samplingFreq = frame->sample_rate; + atx->nbytes = frame->nb_samples * sizeof(float); + if (frame->channels == 1) + { + atx->channelConfigIndex = 1; + } + else if (frame->channels == 2) + { + atx->channelConfigIndex = 2; + } + else + { + cellAdec->Error("cellAdecGetPcmItem(): unsupported channel count (%d)", frame->channels); + Emu.Pause(); + } *pcmItem_ptr = pcm.addr(); - return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 7249fd411e..414d986dee 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -790,7 +790,7 @@ struct CellAdecParamAtracX be_t ch_config_idx; be_t nch_out; be_t nbytes; - u8 extra_config_data[4]; // downmix coefficients + std::array extra_config_data; // downmix coefficients be_t bw_pcm; ATRACX_DownmixFlag downmix_flag; ATRACX_ATSHeaderInclude au_includes_ats_hdr_flg; @@ -1010,6 +1010,18 @@ struct AdecTask u64 pts; u64 userdata; } au; + + struct + { + s32 sample_rate; + s32 channel_config; + s32 channels; + s32 frame_size; + std::array extra_config; + s32 output; + u8 downmix; + u8 ats_header; + } at3p; }; AdecTask(AdecJobType type) @@ -1034,6 +1046,8 @@ struct AdecFrame int adecRead(void* opaque, u8* buf, int buf_size); +static const u32 at3freq[8] = { 32000, 44100, 48000, 88200, 96000, 0, 0, 0 }; + struct OMAHeader // OMA Header { u32 magic; // 0x01334145 @@ -1043,26 +1057,34 @@ struct OMAHeader // OMA Header u64 unk2; // 0xcef5000000000400ULL u64 unk3; // 0x1c458024329192d2ULL u8 codecId; // 1 for ATRAC3P - u8 reserved0; // 0 + u8 code0; // 0 u8 code1; u8 code2; - u32 reserved1; // 0 - u64 reserved[7]; // 0 + u32 reserved[15]; // 0 - OMAHeader(u8 id, u8 code1, u8 code2) + OMAHeader(u8 codec_id, u32 freq, u8 channel_count, u32 frame_size) : magic(0x01334145) , size(96 << 8) , unk0(0xffff) , unk1(0x00500f0100000000ULL) , unk2(0xcef5000000000400ULL) , unk3(0x1c458024329192d2ULL) - , codecId(id) - , reserved0(0) - , code1(code1) - , code2(code2) - , reserved1(0) + , codecId(codec_id) + , code0(0) { memset(reserved, 0, sizeof(reserved)); + + u8 freq_code; + for (freq_code = 0; freq_code < 5; freq_code++) + { + if (at3freq[freq_code] == freq) + { + break; + } + } + u32 prepared_frame_size = (frame_size - 8) / 8; + code1 = ((prepared_frame_size >> 8) & 0x3) | ((channel_count & 0x7) << 2) | (freq_code << 5); + code2 = prepared_frame_size & 0xff; } }; @@ -1087,20 +1109,13 @@ public: u32 addr; u32 size; bool init; - u8* rem; - u32 rem_size; + bool has_ats; AudioReader() - : rem(nullptr) - , rem_size(0) + : init(false) { } - ~AudioReader() - { - if (rem) free(rem); - rem = nullptr; - } } reader; SQueue frames; @@ -1115,6 +1130,11 @@ public: AdecTask task; u64 last_pts, first_pts; + u32 channels; + u32 frame_size; + u32 sample_rate; + bool use_ats_headers; + PPUThread* adecCb; AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr func, u32 arg); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp b/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp index d619d0ff9f..d2cf50a532 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAtrac.cpp @@ -1,48 +1,71 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" Module *cellAtrac = nullptr; #include "cellAtrac.h" -int cellAtracSetDataAndGetMemSize(vm::ptr pHandle, u32 pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, vm::ptr puiWorkMemByte) +#ifdef PRX_DEBUG +#include "prx_libatrac3plus.h" +u32 libatrac3plus; +u32 libatrac3plus_rtoc; +#endif + +s32 cellAtracSetDataAndGetMemSize(vm::ptr pHandle, u32 pucBufferAddr, u32 uiReadByte, u32 uiBufferByte, vm::ptr puiWorkMemByte) { cellAtrac->Todo("cellAtracSetDataAndGetMemSize(pHandle=0x%x, pucBufferAddr=0x%x, uiReadByte=0x%x, uiBufferByte=0x%x, puiWorkMemByte_addr=0x%x)", pHandle.addr(), pucBufferAddr, uiReadByte, uiBufferByte, puiWorkMemByte.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x11F4, libatrac3plus_rtoc); +#endif *puiWorkMemByte = 0x1000; // unproved return CELL_OK; } -int cellAtracCreateDecoder(vm::ptr pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, u32 uiSpuThreadPriority) +s32 cellAtracCreateDecoder(vm::ptr pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, u32 uiSpuThreadPriority) { cellAtrac->Todo("cellAtracCreateDecoder(pHandle=0x%x, pucWorkMem_addr=0x%x, uiPpuThreadPriority=%d, uiSpuThreadPriority=%d)", pHandle.addr(), pucWorkMem_addr, uiPpuThreadPriority, uiSpuThreadPriority); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0FF0, libatrac3plus_rtoc); +#endif pHandle->data.pucWorkMem_addr = pucWorkMem_addr; return CELL_OK; } -int cellAtracCreateDecoderExt(vm::ptr pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, vm::ptr pExtRes) +s32 cellAtracCreateDecoderExt(vm::ptr pHandle, u32 pucWorkMem_addr, u32 uiPpuThreadPriority, vm::ptr pExtRes) { cellAtrac->Todo("cellAtracCreateDecoderExt(pHandle=0x%x, pucWorkMem_addr=0x%x, uiPpuThreadPriority=%d, pExtRes_addr=0x%x)", pHandle.addr(), pucWorkMem_addr, uiPpuThreadPriority, pExtRes.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0DB0, libatrac3plus_rtoc); +#endif pHandle->data.pucWorkMem_addr = pucWorkMem_addr; return CELL_OK; } -int cellAtracDeleteDecoder(vm::ptr pHandle) +s32 cellAtracDeleteDecoder(vm::ptr pHandle) { cellAtrac->Todo("cellAtracDeleteDecoder(pHandle=0x%x)", pHandle.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0D08, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracDecode(vm::ptr pHandle, u32 pfOutAddr, vm::ptr puiSamples, vm::ptr puiFinishflag, vm::ptr piRemainFrame) +s32 cellAtracDecode(vm::ptr pHandle, u32 pfOutAddr, vm::ptr puiSamples, vm::ptr puiFinishflag, vm::ptr piRemainFrame) { cellAtrac->Todo("cellAtracDecode(pHandle=0x%x, pfOutAddr=0x%x, puiSamples_addr=0x%x, puiFinishFlag_addr=0x%x, piRemainFrame_addr=0x%x)", pHandle.addr(), pfOutAddr, puiSamples.addr(), puiFinishflag.addr(), piRemainFrame.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x09A8, libatrac3plus_rtoc); +#endif *puiSamples = 0; *puiFinishflag = 1; @@ -50,10 +73,13 @@ int cellAtracDecode(vm::ptr pHandle, u32 pfOutAddr, vm::ptr pHandle, vm::ptr ppucWritePointer, vm::ptr puiWritableByte, vm::ptr puiReadPosition) +s32 cellAtracGetStreamDataInfo(vm::ptr pHandle, vm::ptr ppucWritePointer, vm::ptr puiWritableByte, vm::ptr puiReadPosition) { cellAtrac->Todo("cellAtracGetStreamDataInfo(pHandle=0x%x, ppucWritePointer_addr=0x%x, puiWritableByte_addr=0x%x, puiReadPosition_addr=0x%x)", pHandle.addr(), ppucWritePointer.addr(), puiWritableByte.addr(), puiReadPosition.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0BE8, libatrac3plus_rtoc); +#endif *ppucWritePointer = pHandle->data.pucWorkMem_addr; *puiWritableByte = 0x1000; @@ -61,79 +87,112 @@ int cellAtracGetStreamDataInfo(vm::ptr pHandle, vm::ptr pp return CELL_OK; } -int cellAtracAddStreamData(vm::ptr pHandle, u32 uiAddByte) +s32 cellAtracAddStreamData(vm::ptr pHandle, u32 uiAddByte) { cellAtrac->Todo("cellAtracAddStreamData(pHandle=0x%x, uiAddByte=0x%x)", pHandle.addr(), uiAddByte); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0AFC, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracGetRemainFrame(vm::ptr pHandle, vm::ptr piRemainFrame) +s32 cellAtracGetRemainFrame(vm::ptr pHandle, vm::ptr piRemainFrame) { cellAtrac->Todo("cellAtracGetRemainFrame(pHandle=0x%x, piRemainFrame_addr=0x%x)", pHandle.addr(), piRemainFrame.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x092C, libatrac3plus_rtoc); +#endif *piRemainFrame = CELL_ATRAC_ALLDATA_IS_ON_MEMORY; return CELL_OK; } -int cellAtracGetVacantSize(vm::ptr pHandle, vm::ptr puiVacantSize) +s32 cellAtracGetVacantSize(vm::ptr pHandle, vm::ptr puiVacantSize) { cellAtrac->Todo("cellAtracGetVacantSize(pHandle=0x%x, puiVacantSize_addr=0x%x)", pHandle.addr(), puiVacantSize.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x08B0, libatrac3plus_rtoc); +#endif *puiVacantSize = 0x1000; return CELL_OK; } -int cellAtracIsSecondBufferNeeded(vm::ptr pHandle) +s32 cellAtracIsSecondBufferNeeded(vm::ptr pHandle) { cellAtrac->Todo("cellAtracIsSecondBufferNeeded(pHandle=0x%x)", pHandle.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0010, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracGetSecondBufferInfo(vm::ptr pHandle, vm::ptr puiReadPosition, vm::ptr puiDataByte) +s32 cellAtracGetSecondBufferInfo(vm::ptr pHandle, vm::ptr puiReadPosition, vm::ptr puiDataByte) { cellAtrac->Todo("cellAtracGetSecondBufferInfo(pHandle=0x%x, puiReadPosition_addr=0x%x, puiDataByte_addr=0x%x)", pHandle.addr(), puiReadPosition.addr(), puiDataByte.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x07E8, libatrac3plus_rtoc); +#endif *puiReadPosition = 0; *puiDataByte = 0; // write to null block will occur return CELL_OK; } -int cellAtracSetSecondBuffer(vm::ptr pHandle, u32 pucSecondBufferAddr, u32 uiSecondBufferByte) +s32 cellAtracSetSecondBuffer(vm::ptr pHandle, u32 pucSecondBufferAddr, u32 uiSecondBufferByte) { cellAtrac->Todo("cellAtracSetSecondBuffer(pHandle=0x%x, pucSecondBufferAddr=0x%x, uiSecondBufferByte=0x%x)", pHandle.addr(), pucSecondBufferAddr, uiSecondBufferByte); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0704, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracGetChannel(vm::ptr pHandle, vm::ptr puiChannel) +s32 cellAtracGetChannel(vm::ptr pHandle, vm::ptr puiChannel) { cellAtrac->Todo("cellAtracGetChannel(pHandle=0x%x, puiChannel_addr=0x%x)", pHandle.addr(), puiChannel.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0060, libatrac3plus_rtoc); +#endif *puiChannel = 2; return CELL_OK; } -int cellAtracGetMaxSample(vm::ptr pHandle, vm::ptr puiMaxSample) +s32 cellAtracGetMaxSample(vm::ptr pHandle, vm::ptr puiMaxSample) { cellAtrac->Todo("cellAtracGetMaxSample(pHandle=0x%x, puiMaxSample_addr=0x%x)", pHandle.addr(), puiMaxSample.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x00AC, libatrac3plus_rtoc); +#endif *puiMaxSample = 512; return CELL_OK; } -int cellAtracGetNextSample(vm::ptr pHandle, vm::ptr puiNextSample) +s32 cellAtracGetNextSample(vm::ptr pHandle, vm::ptr puiNextSample) { cellAtrac->Todo("cellAtracGetNextSample(pHandle=0x%x, puiNextSample_addr=0x%x)", pHandle.addr(), puiNextSample.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0688, libatrac3plus_rtoc); +#endif *puiNextSample = 0; return CELL_OK; } -int cellAtracGetSoundInfo(vm::ptr pHandle, vm::ptr piEndSample, vm::ptr piLoopStartSample, vm::ptr piLoopEndSample) +s32 cellAtracGetSoundInfo(vm::ptr pHandle, vm::ptr piEndSample, vm::ptr piLoopStartSample, vm::ptr piLoopEndSample) { cellAtrac->Todo("cellAtracGetSoundInfo(pHandle=0x%x, piEndSample_addr=0x%x, piLoopStartSample_addr=0x%x, piLoopEndSample_addr=0x%x)", pHandle.addr(), piEndSample.addr(), piLoopStartSample.addr(), piLoopEndSample.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0104, libatrac3plus_rtoc); +#endif *piEndSample = 0; *piLoopStartSample = 0; @@ -141,44 +200,60 @@ int cellAtracGetSoundInfo(vm::ptr pHandle, vm::ptr piEndSa return CELL_OK; } -int cellAtracGetNextDecodePosition(vm::ptr pHandle, vm::ptr puiSamplePosition) +s32 cellAtracGetNextDecodePosition(vm::ptr pHandle, vm::ptr puiSamplePosition) { cellAtrac->Todo("cellAtracGetNextDecodePosition(pHandle=0x%x, puiSamplePosition_addr=0x%x)", pHandle.addr(), puiSamplePosition.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0190, libatrac3plus_rtoc); +#endif *puiSamplePosition = 0; return CELL_ATRAC_ERROR_ALLDATA_WAS_DECODED; } -int cellAtracGetBitrate(vm::ptr pHandle, vm::ptr puiBitrate) +s32 cellAtracGetBitrate(vm::ptr pHandle, vm::ptr puiBitrate) { cellAtrac->Todo("cellAtracGetBitrate(pHandle=0x%x, puiBitrate_addr=0x%x)", pHandle.addr(), puiBitrate.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x0374, libatrac3plus_rtoc); +#endif *puiBitrate = 128; return CELL_OK; } -int cellAtracGetLoopInfo(vm::ptr pHandle, vm::ptr piLoopNum, vm::ptr puiLoopStatus) +s32 cellAtracGetLoopInfo(vm::ptr pHandle, vm::ptr piLoopNum, vm::ptr puiLoopStatus) { cellAtrac->Todo("cellAtracGetLoopInfo(pHandle=0x%x, piLoopNum_addr=0x%x, puiLoopStatus_addr=0x%x)", pHandle.addr(), piLoopNum.addr(), puiLoopStatus.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x025C, libatrac3plus_rtoc); +#endif *piLoopNum = 0; *puiLoopStatus = 0; return CELL_OK; } -int cellAtracSetLoopNum(vm::ptr pHandle, int iLoopNum) +s32 cellAtracSetLoopNum(vm::ptr pHandle, int iLoopNum) { cellAtrac->Todo("cellAtracSetLoopNum(pHandle=0x%x, iLoopNum=0x%x)", pHandle.addr(), iLoopNum); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x1538, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracGetBufferInfoForResetting(vm::ptr pHandle, u32 uiSample, vm::ptr pBufferInfo) +s32 cellAtracGetBufferInfoForResetting(vm::ptr pHandle, u32 uiSample, vm::ptr pBufferInfo) { cellAtrac->Todo("cellAtracGetBufferInfoForResetting(pHandle=0x%x, uiSample=0x%x, pBufferInfo_addr=0x%x)", pHandle.addr(), uiSample, pBufferInfo.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x05BC, libatrac3plus_rtoc); +#endif pBufferInfo->pucWriteAddr = pHandle->data.pucWorkMem_addr; pBufferInfo->uiWritableByte = 0x1000; @@ -187,17 +262,24 @@ int cellAtracGetBufferInfoForResetting(vm::ptr pHandle, u32 uiS return CELL_OK; } -int cellAtracResetPlayPosition(vm::ptr pHandle, u32 uiSample, u32 uiWriteByte) +s32 cellAtracResetPlayPosition(vm::ptr pHandle, u32 uiSample, u32 uiWriteByte) { cellAtrac->Todo("cellAtracResetPlayPosition(pHandle=0x%x, uiSample=0x%x, uiWriteByte=0x%x)", pHandle.addr(), uiSample, uiWriteByte); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x04E4, libatrac3plus_rtoc); +#endif + return CELL_OK; } -int cellAtracGetInternalErrorInfo(vm::ptr pHandle, vm::ptr piResult) +s32 cellAtracGetInternalErrorInfo(vm::ptr pHandle, vm::ptr piResult) { cellAtrac->Todo("cellAtracGetInternalErrorInfo(pHandle=0x%x, piResult_addr=0x%x)", pHandle.addr(), piResult.addr()); +#ifdef PRX_DEBUG + return GetCurrentPPUThread().FastCall2(libatrac3plus + 0x02E4, libatrac3plus_rtoc); +#endif *piResult = 0; return CELL_OK; @@ -237,4 +319,25 @@ void cellAtrac_init(Module *pxThis) cellAtrac->AddFunc(0x7772eb2b, cellAtracResetPlayPosition); cellAtrac->AddFunc(0xb5c11938, cellAtracGetInternalErrorInfo); + +#ifdef PRX_DEBUG + CallAfter([]() + { + libatrac3plus = (u32)Memory.MainMem.AllocAlign(sizeof(libatrac3plus_data), 0x100000); + memcpy(vm::get_ptr(libatrac3plus), libatrac3plus_data, sizeof(libatrac3plus_data)); + libatrac3plus_rtoc = libatrac3plus + 0xBED0; + + extern Module* cellAdec; + + FIX_IMPORT(cellAdec, cellAdecDecodeAu, libatrac3plus + 0x399C); + FIX_IMPORT(cellAdec, cellAdecStartSeq, libatrac3plus + 0x39BC); + FIX_IMPORT(cellAdec, cellAdecQueryAttr, libatrac3plus + 0x39DC); + FIX_IMPORT(cellAdec, cellAdecClose, libatrac3plus + 0x39FC); + FIX_IMPORT(cellAdec, cellAdecGetPcm, libatrac3plus + 0x3A1C); + FIX_IMPORT(cellAdec, cellAdecOpen, libatrac3plus + 0x3A3C); + fix_import(cellAdec, 0xDF982D2C, libatrac3plus + 0x3A5C); + + fix_relocs(cellAtrac, libatrac3plus, 0x3EF0, 0x5048, 0x3CE0); + }); +#endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAtrac.h b/rpcs3/Emu/SysCalls/Modules/cellAtrac.h index 809bcc6d10..c6102316b9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAtrac.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAtrac.h @@ -3,7 +3,6 @@ // Return Codes enum { - CELL_ATRAC_OK = 0x00000000, CELL_ATRAC_ERROR_API_FAIL = 0x80610301, CELL_ATRAC_ERROR_READSIZE_OVER_BUFFER = 0x80610311, CELL_ATRAC_ERROR_UNKNOWN_FORMAT = 0x80610312, @@ -27,6 +26,32 @@ enum CELL_ATRAC_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610382, }; +enum +{ + CELL_ATRACMULTI_ERROR_API_FAIL = 0x80610b01, + CELL_ATRACMULTI_ERROR_READSIZE_OVER_BUFFER = 0x80610b11, + CELL_ATRACMULTI_ERROR_UNKNOWN_FORMAT = 0x80610b12, + CELL_ATRACMULTI_ERROR_READSIZE_IS_TOO_SMALL = 0x80610b13, + CELL_ATRACMULTI_ERROR_ILLEGAL_SAMPLING_RATE = 0x80610b14, + CELL_ATRACMULTI_ERROR_ILLEGAL_DATA = 0x80610b15, + CELL_ATRACMULTI_ERROR_NO_DECODER = 0x80610b21, + CELL_ATRACMULTI_ERROR_UNSET_DATA = 0x80610b22, + CELL_ATRACMULTI_ERROR_DECODER_WAS_CREATED = 0x80610b23, + CELL_ATRACMULTI_ERROR_ALLDATA_WAS_DECODED = 0x80610b31, + CELL_ATRACMULTI_ERROR_NODATA_IN_BUFFER = 0x80610b32, + CELL_ATRACMULTI_ERROR_NOT_ALIGNED_OUT_BUFFER = 0x80610b33, + CELL_ATRACMULTI_ERROR_NEED_SECOND_BUFFER = 0x80610b34, + CELL_ATRACMULTI_ERROR_ALLDATA_IS_ONMEMORY = 0x80610b41, + CELL_ATRACMULTI_ERROR_ADD_DATA_IS_TOO_BIG = 0x80610b42, + CELL_ATRACMULTI_ERROR_NONEED_SECOND_BUFFER = 0x80610b51, + CELL_ATRACMULTI_ERROR_UNSET_LOOP_NUM = 0x80610b61, + CELL_ATRACMULTI_ERROR_ILLEGAL_SAMPLE = 0x80610b71, + CELL_ATRACMULTI_ERROR_ILLEGAL_RESET_BYTE = 0x80610b72, + CELL_ATRACMULTI_ERROR_ILLEGAL_PPU_THREAD_PRIORITY = 0x80610b81, + CELL_ATRACMULTI_ERROR_ILLEGAL_SPU_THREAD_PRIORITY = 0x80610b82, + CELL_ATRACMULTI_ERROR_API_PARAMETER = 0x80610b91, +}; + // Remain Frame enum { @@ -38,6 +63,7 @@ enum union CellAtracHandle { u8 uiWorkMem[512]; + struct AtracHandle { u32 pucWorkMem_addr; @@ -56,4 +82,4 @@ struct CellAtracExtRes { be_t pSpurs_addr; u8 priority[8]; -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 0b179d54e1..f302a9fc2f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -337,7 +337,7 @@ int cellAudioInit() // 2x MAXPS (optional) // 2x MINPS (optional) // 2x CVTPS2DQ (converts float to s32) - // PACKSSDW (converts s32 to s16 with clipping) + // PACKSSDW (converts s32 to s16 with signed saturation) if (g_is_u16) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 0c8704c934..116169406e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -401,11 +401,6 @@ u32 dmuxOpen(Demuxer* data) PesHeader pes(stream); - if (!pes.new_au) // temporarily - { - cellDmux->Error("No pts info found"); - } - // read additional header: stream.peek(ch); // ??? //stream.skip(4);