CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/HLE/sceAudiocodec.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include "Common/Serialize/Serializer.h"1819#include "Common/Serialize/SerializeFuncs.h"20#include "Core/HLE/HLE.h"21#include "Core/HLE/FunctionWrappers.h"22#include "Core/HLE/sceAudiocodec.h"23#include "Core/MemMap.h"24#include "Core/Reporting.h"25#include "Core/HW/SimpleAudioDec.h"2627// Following kaien_fr's sample code https://github.com/hrydgard/ppsspp/issues/5620#issuecomment-3708602428// Should probably store the EDRAM get/release status somewhere within here, etc.29struct AudioCodecContext {30u32_le unknown[6];31u32_le inDataPtr; // 632u32_le inDataSize; // 733u32_le outDataPtr; // 834u32_le audioSamplesPerFrame; // 935u32_le inDataSizeAgain; // 10 ??36};3738// audioList is to store current playing audios.39static std::map<u32, AudioDecoder *> audioList;4041static bool oldStateLoaded = false;4243// find the audio decoder for corresponding ctxPtr in audioList44static AudioDecoder *findDecoder(u32 ctxPtr) {45auto it = audioList.find(ctxPtr);46if (it != audioList.end()) {47return it->second;48}49return NULL;50}5152// remove decoder from audioList53static bool removeDecoder(u32 ctxPtr) {54auto it = audioList.find(ctxPtr);55if (it != audioList.end()) {56delete it->second;57audioList.erase(it);58return true;59}60return false;61}6263static void clearDecoders() {64for (const auto &[_, decoder] : audioList) {65delete decoder;66}67audioList.clear();68}6970void __AudioCodecInit() {71oldStateLoaded = false;72}7374void __AudioCodecShutdown() {75// We need to kill off any still opened codecs to not leak memory.76clearDecoders();77}7879static int sceAudiocodecInit(u32 ctxPtr, int codec) {80PSPAudioType audioType = (PSPAudioType)codec;81if (IsValidCodec(audioType)) {82// Create audio decoder for given audio codec and push it into AudioList83if (removeDecoder(ctxPtr)) {84WARN_LOG_REPORT(Log::HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec);85}86AudioDecoder *decoder = CreateAudioDecoder(audioType);87decoder->SetCtxPtr(ctxPtr);88audioList[ctxPtr] = decoder;89INFO_LOG(Log::ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(audioType));90DEBUG_LOG(Log::ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size());91return 0;92}93ERROR_LOG_REPORT(Log::ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(audioType), codec);94return 0;95}9697static int sceAudiocodecDecode(u32 ctxPtr, int codec) {98PSPAudioType audioType = (PSPAudioType)codec;99if (!ctxPtr){100ERROR_LOG_REPORT(Log::ME, "sceAudiocodecDecode(%08x, %i (%s)) got NULL pointer", ctxPtr, codec, GetCodecName(audioType));101return -1;102}103104if (IsValidCodec(audioType)){105// find a decoder in audioList106auto decoder = findDecoder(ctxPtr);107108if (!decoder && oldStateLoaded) {109// We must have loaded an old state that did not have sceAudiocodec information.110// Fake it by creating the desired context.111decoder = CreateAudioDecoder(audioType);112decoder->SetCtxPtr(ctxPtr);113audioList[ctxPtr] = decoder;114}115116if (decoder != NULL) {117// Use SimpleAudioDec to decode audio118auto ctx = PSPPointer<AudioCodecContext>::Create(ctxPtr); // On stack, no need to allocate.119// Decode audio120int inDataConsumed = 0;121int outSamples = 0;122decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, &inDataConsumed, 2, (int16_t *)Memory::GetPointerWrite(ctx->outDataPtr), &outSamples);123}124DEBUG_LOG(Log::ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));125return 0;126}127ERROR_LOG_REPORT(Log::ME, "UNIMPL sceAudiocodecDecode(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));128return 0;129}130131static int sceAudiocodecGetInfo(u32 ctxPtr, int codec) {132ERROR_LOG_REPORT(Log::ME, "UNIMPL sceAudiocodecGetInfo(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));133return 0;134}135136static int sceAudiocodecCheckNeedMem(u32 ctxPtr, int codec) {137WARN_LOG(Log::ME, "UNIMPL sceAudiocodecCheckNeedMem(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));138return 0;139}140141static int sceAudiocodecGetEDRAM(u32 ctxPtr, int codec) {142WARN_LOG(Log::ME, "UNIMPL sceAudiocodecGetEDRAM(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));143return 0;144}145146static int sceAudiocodecReleaseEDRAM(u32 ctxPtr, int id) {147if (removeDecoder(ctxPtr)){148INFO_LOG(Log::ME, "sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);149return 0;150}151WARN_LOG(Log::ME, "UNIMPL sceAudiocodecReleaseEDRAM(%08x, %i)", ctxPtr, id);152return 0;153}154155const HLEFunction sceAudiocodec[] = {156{0X70A703F8, &WrapI_UI<sceAudiocodecDecode>, "sceAudiocodecDecode", 'i', "xi"},157{0X5B37EB1D, &WrapI_UI<sceAudiocodecInit>, "sceAudiocodecInit", 'i', "xi"},158{0X8ACA11D5, &WrapI_UI<sceAudiocodecGetInfo>, "sceAudiocodecGetInfo", 'i', "xi"},159{0X3A20A200, &WrapI_UI<sceAudiocodecGetEDRAM>, "sceAudiocodecGetEDRAM", 'i', "xi"},160{0X29681260, &WrapI_UI<sceAudiocodecReleaseEDRAM>, "sceAudiocodecReleaseEDRAM", 'i', "xi"},161{0X9D3F790C, &WrapI_UI<sceAudiocodecCheckNeedMem>, "sceAudiocodecCheckNeedMem", 'i', "xi"},162{0X59176A0F, nullptr, "sceAudiocodecAlcExtendParameter", '?', "" },163};164165void Register_sceAudiocodec()166{167RegisterModule("sceAudiocodec", ARRAY_SIZE(sceAudiocodec), sceAudiocodec);168}169170void __sceAudiocodecDoState(PointerWrap &p){171auto s = p.Section("AudioList", 0, 2);172if (!s) {173oldStateLoaded = true;174return;175}176177int count = (int)audioList.size();178Do(p, count);179180if (count > 0) {181if (p.mode == PointerWrap::MODE_READ) {182clearDecoders();183184// loadstate if audioList is nonempty185auto codec_ = new int[count];186auto ctxPtr_ = new u32[count];187// These sizeof(pointers) are wrong, but kept to avoid breaking on old saves.188// They're not used in new savestates.189#ifdef __clang__190#pragma clang diagnostic push191#pragma clang diagnostic ignored "-Wunknown-warning-option"192#pragma clang diagnostic ignored "-Wsizeof-pointer-div"193#elif defined(__GNUC__)194#pragma GCC diagnostic push195#pragma GCC diagnostic ignored "-Wsizeof-pointer-div"196#endif197DoArray(p, codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));198DoArray(p, ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));199for (int i = 0; i < count; i++) {200auto decoder = CreateAudioDecoder((PSPAudioType)codec_[i]);201decoder->SetCtxPtr(ctxPtr_[i]);202audioList[ctxPtr_[i]] = decoder;203}204#ifdef __clang__205#pragma clang diagnostic pop206#elif defined(__GNUC__)207#pragma GCC diagnostic pop208#endif209delete[] codec_;210delete[] ctxPtr_;211}212else213{214// savestate if audioList is nonempty215// Some of this is only necessary in Write but won't really hurt Measure.216auto codec_ = new int[count];217auto ctxPtr_ = new u32[count];218int i = 0;219for (auto iter : audioList) {220const AudioDecoder *decoder = iter.second;221codec_[i] = decoder->GetAudioType();222ctxPtr_[i] = decoder->GetCtxPtr();223i++;224}225DoArray(p, codec_, count);226DoArray(p, ctxPtr_, count);227delete[] codec_;228delete[] ctxPtr_;229}230}231}232233234