diff --git a/CMakeLists.txt b/CMakeLists.txt index ff17c71bae..9df05408ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -797,6 +797,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/sceP3da.h Core/HLE/sceMp4.cpp Core/HLE/sceMp4.h + Core/HLE/sceMp3.cpp + Core/HLE/sceMp3.h Core/HLE/sceParseHttp.cpp Core/HLE/sceParseHttp.h Core/HLE/sceParseUri.cpp diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 0712c928d5..2e92313dec 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRCS HLE/sceNp.cpp HLE/sceP3da.cpp HLE/sceMp4.cpp + HLE/sceMp3.cpp HLE/scePauth.cpp HLE/scePower.cpp HLE/scePsmf.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 879a5388bf..9ee56febd4 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -211,6 +211,7 @@ + @@ -383,6 +384,7 @@ + diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index dfd35e1cf4..932a8f936b 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -59,6 +59,7 @@ #include "sceGameUpdate.h" #include "sceDeflt.h" #include "sceMp4.h" +#include "sceMp3.h" #include "scePauth.h" #include "sceNp.h" diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp new file mode 100644 index 0000000000..6808a08e2e --- /dev/null +++ b/Core/HLE/sceMp3.cpp @@ -0,0 +1,414 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include "HLE.h" +#include "../HW/MediaEngine.h" + +static const int MP3_BITRATES[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; + +struct Mp3Context { + Mp3Context() : mediaengine(NULL) {} + ~Mp3Context() { + if (mediaengine != NULL) { + delete mediaengine; + } + } + + void DoState(PointerWrap &p) { + p.Do(mp3StreamStart); + p.Do(mp3StreamEnd); + p.Do(mp3Buf); + p.Do(mp3BufSize); + p.Do(mp3PcmBuf); + p.Do(mp3BufPendingSize); + p.Do(mp3PcmBufSize); + p.Do(mp3InputFileReadPos); + p.Do(mp3InputBufWritePos); + p.Do(mp3InputBufSize); + p.Do(mp3InputFileSize); + p.Do(mp3DecodedBytes); + p.Do(mp3LoopNum); + p.Do(mp3MaxSamples); + p.Do(mp3Bitrate); + p.Do(mp3Channels); + p.Do(mp3SamplingRate); + p.Do(mp3Version); + p.DoClass(mediaengine); + p.DoMarker("Mp3Context"); + } + + u64 mp3StreamStart; + u64 mp3StreamEnd; + u64 mp3StreamPosition; + u32 mp3Buf; + int mp3BufSize; + int mp3BufPendingSize; + u32 mp3PcmBuf; + int mp3PcmBufSize; + + int mp3InputFileReadPos; + int mp3InputBufWritePos; + int mp3InputBufSize; + int mp3InputFileSize; + int mp3DecodedBytes; + int mp3LoopNum; + int mp3MaxSamples; + + int mp3Channels; + int mp3Bitrate; + int mp3SamplingRate; + int mp3Version; + + MediaEngine *mediaengine; +}; + + +static std::map mp3Map; +static u32 lastMp3Handle = 0; + +Mp3Context *getMp3Ctx(u32 mp3) { + if (mp3Map.find(mp3) == mp3Map.end()) { + ERROR_LOG(HLE, "Bad mp3 handle %08x - using last one (%08x) instead", mp3, lastMp3Handle); + mp3 = lastMp3Handle; + } + if (mp3Map.find(mp3) == mp3Map.end()) + return NULL; + return mp3Map[mp3]; +} + +int sceMp3Decode(u32 mp3, u32 outPcmPtr) { + DEBUG_LOG(HLE, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + + // Nothing to decode + if(ctx->mp3BufPendingSize == 0 || ctx->mp3StreamPosition >= ctx->mp3StreamEnd) { + if (ctx->mp3LoopNum == 0) { + return 0; + } else if (ctx->mp3LoopNum > 0) { + --ctx->mp3LoopNum; + } + } + + Memory::Memset(ctx->mp3PcmBuf, 0, ctx->mp3PcmBufSize); + Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); + + // TODO: Actually decode the data +#ifdef _DEBUG + char fileName[256]; + sprintf(fileName, "%lli.mp3", ctx->mp3StreamPosition); + + FILE * file = fopen(fileName, "wb"); + if(file) { + if(!Memory::IsValidAddress(ctx->mp3Buf)) { + ERROR_LOG(HLE, "sceMp3Decode mp3Buf %08X is not a valid address!", ctx->mp3Buf); + } + + u8 * ptr = Memory::GetPointer(ctx->mp3Buf); + fwrite(ptr, 1, ctx->mp3BufPendingSize, file); + + fclose(file); + } +#endif + + ctx->mp3StreamPosition += ctx->mp3BufPendingSize; + if(ctx->mp3StreamPosition > ctx->mp3StreamEnd) + ctx->mp3StreamPosition = ctx->mp3StreamEnd; + + // Reset the pending buffer size so the program will know that we need to buffer more data + ctx->mp3BufPendingSize = (ctx->mp3StreamPosition < ctx->mp3StreamEnd)?-1:0; + + return ctx->mp3PcmBufSize; +} + +int sceMp3ResetPlayPosition(u32 mp3) { + DEBUG_LOG(HLE, "SceMp3ResetPlayPosition(%08x)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + ctx->mp3StreamPosition = 0; + ctx->mp3BufPendingSize = -1; + return 0; +} + +int sceMp3CheckStreamDataNeeded(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3CheckStreamDataNeeded(%08x)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return (ctx->mp3BufPendingSize < 0) && (ctx->mp3StreamPosition < ctx->mp3StreamEnd); +} + +u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { + DEBUG_LOG(HLE, "sceMp3ReserveMp3Handle(%08x)", mp3Addr); + Mp3Context *ctx = new Mp3Context; + + memset(ctx, 0, sizeof(Mp3Context)); + + ctx->mp3StreamStart = Memory::Read_U64(mp3Addr); + ctx->mp3StreamEnd = Memory::Read_U64(mp3Addr+8); + ctx->mp3Buf = Memory::Read_U32(mp3Addr+16); + ctx->mp3BufSize = Memory::Read_U32(mp3Addr+20); + ctx->mp3PcmBuf = Memory::Read_U32(mp3Addr+24); + ctx->mp3PcmBufSize = Memory::Read_U32(mp3Addr+28); + + ctx->mp3StreamPosition = ctx->mp3StreamStart; + ctx->mp3BufPendingSize = -1; + ctx->mp3MaxSamples = ctx->mp3PcmBufSize / 4 ; + + /*ctx->mp3Channels = 2; + ctx->mp3Bitrate = 128; + ctx->mp3SamplingRate = 44100;*/ + + mp3Map[mp3Addr] = ctx; + return mp3Addr; +} + +int sceMp3InitResource() { + WARN_LOG(HLE, "UNIML: sceMp3InitResource"); + // Do nothing here + return 0; +} + +int sceMp3TermResource() { + WARN_LOG(HLE, "UNIML: sceMp3TermResource"); + // Do nothing here + return 0; +} + +int sceMp3Init(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3Init(%08x)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + + // Read in the header and swap the endian + int header = Memory::Read_U32(ctx->mp3Buf); + header = (header >> 24) | + ((header<<8) & 0x00FF0000) | + ((header>>8) & 0x0000FF00) | + (header << 24); + + int channels = ((header >> 6) & 0x3); + if(channels == 0 || channels == 1 || channels == 2) + ctx->mp3Channels = 2; + else if(channels == 3) + ctx->mp3Channels = 1; + else + ctx->mp3Channels = 0; + + // 0 == VBR + int bitrate = ((header >> 10) & 0x3); + if(bitrate < (int)ARRAY_SIZE(MP3_BITRATES)) + ctx->mp3Bitrate = MP3_BITRATES[bitrate]; + else + ctx->mp3Bitrate = -1; + + int samplerate = ((header >> 12) & 0x3); + if (samplerate == 0) + ctx->mp3SamplingRate = 44100; + else if (samplerate == 1) + ctx->mp3SamplingRate = 48000; + else if (samplerate == 2) + ctx->mp3SamplingRate = 32000; + else + ctx->mp3SamplingRate = 0; + + ctx->mp3Version = ((header >> 19) & 0x3); + return 0; +} + +int sceMp3GetLoopNum(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetLoopNum(%08x)", mp3); + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3LoopNum; +} + +int sceMp3GetMaxOutputSample(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetMaxOutputSample(%08x)", mp3); + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3MaxSamples; +} + +int sceMp3NotifyAddStreamData(u32 mp3, int size) { + DEBUG_LOG(HLE, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + ctx->mp3BufPendingSize = size; + return 0; +} + +int sceMp3GetSumDecodedSample(u32 mp3) { + DEBUG_LOG(HLE, "UNIMPL: sceMp3GetSumDecodedSample(%08X)", mp3); + return 0; +} + +int sceMp3SetLoopNum(u32 mp3, int loop) { + DEBUG_LOG(HLE, "sceMp3SetLoopNum(%08X, %i)", mp3, loop); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + ctx->mp3LoopNum = loop; + return 0; +} + +int sceMp3GetMp3ChannelNum(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetMp3ChannelNum(%08X)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3Channels; +} + +int sceMp3GetBitRate(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetBitRate(%08X)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3Bitrate; +} + +int sceMp3GetSamplingRate(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetSamplingRate(%08X)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3SamplingRate; +} + +int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) { + DEBUG_LOG(HLE, "HACK: sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + if(Memory::IsValidAddress(dstPtr)) + Memory::Write_U32(ctx->mp3Buf, dstPtr); + if(Memory::IsValidAddress(towritePtr)) + Memory::Write_U32(ctx->mp3BufSize, towritePtr); + if(Memory::IsValidAddress(srcposPtr)) + Memory::Write_U32((u32)ctx->mp3StreamPosition, srcposPtr); + return 0; +} + +int sceMp3ReleaseMp3Handle(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3ReleaseMp3Handle(%08X)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + mp3Map.erase(mp3Map.find(mp3)); + delete ctx; + return 0; +} + +u32 sceMp3EndEntry() { + DEBUG_LOG(HLE, "UNIMPL sceMp3StartEntry(.)"); + return 0; +} + +u32 sceMp3StartEntry() { + DEBUG_LOG(HLE, "UNIMPL sceMp3StartEntry(.)"); + return 0; +} + +u32 sceMp3GetFrameNum(u32 mp3) { + DEBUG_LOG(HLE, "UNIMPL sceMp3GetFrameNum(%08x)", mp3); + return 0; +} + +u32 sceMp3GetVersion(u32 mp3) { + DEBUG_LOG(HLE, "sceMp3GetVersion(%08x)", mp3); + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + return ctx->mp3Version; +} + +const HLEFunction sceMp3[] = +{ + {0x07EC321A,WrapU_U,"sceMp3ReserveMp3Handle"}, + {0x0DB149F4,WrapI_UI,"sceMp3NotifyAddStreamData"}, + {0x2A368661,WrapI_U,"sceMp3ResetPlayPosition"}, + {0x354D27EA,WrapI_U,"sceMp3GetSumDecodedSample"}, + {0x35750070,WrapI_V,"sceMp3InitResource"}, + {0x3C2FA058,WrapI_V,"sceMp3TermResource"}, + {0x3CEF484F,WrapI_UI,"sceMp3SetLoopNum"}, + {0x44E07129,WrapI_U,"sceMp3Init"}, + {0x732B042A,WrapU_V,"sceMp3EndEntry"}, + {0x7F696782,WrapI_U,"sceMp3GetMp3ChannelNum"}, + {0x87677E40,WrapI_U,"sceMp3GetBitRate"}, + {0x87C263D1,WrapI_U,"sceMp3GetMaxOutputSample"}, + {0x8AB81558,WrapU_V,"sceMp3StartEntry"}, + {0x8F450998,WrapI_U,"sceMp3GetSamplingRate"}, + {0xA703FE0F,WrapI_UUUU,"sceMp3GetInfoToAddStreamData"}, + {0xD021C0FB,WrapI_UU,"sceMp3Decode"}, + {0xD0A56296,WrapI_U,"sceMp3CheckStreamDataNeeded"}, + {0xD8F54A51,WrapI_U,"sceMp3GetLoopNum"}, + {0xF5478233,WrapI_U,"sceMp3ReleaseMp3Handle"}, + {0xAE6D2027,WrapU_U,"sceMp3GetVersion"}, + {0x3548AEC8,WrapU_U,"sceMp3GetFrameNum"}, +}; + +void Register_sceMp3() +{ + RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3); +} diff --git a/Core/HLE/sceMp3.h b/Core/HLE/sceMp3.h new file mode 100644 index 0000000000..f855286ecd --- /dev/null +++ b/Core/HLE/sceMp3.h @@ -0,0 +1,22 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "HLE.h" + +void Register_sceMp3(); \ No newline at end of file diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 50db92c0d6..8fb8f9bf93 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -83,8 +83,6 @@ static const int PSP_ERROR_MPEG_NO_DATA = 0x80618001; static const int TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650 = 0X00; static const int TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888 = 0X03; -static const int MP3_BITRATES[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; - int getMaxAheadTimestamp(const SceMpegRingBuffer &ringbuf) { return std::max(40000, ringbuf.packets * 700); // empiric value from JPCSP, thanks! } @@ -97,62 +95,6 @@ struct AvcContext { int avcFrameStatus; }; -struct Mp3Context { - Mp3Context() : mediaengine(NULL) {} - ~Mp3Context() { - if (mediaengine != NULL) { - delete mediaengine; - } - } - - void DoState(PointerWrap &p) { - p.Do(mp3StreamStart); - p.Do(mp3StreamEnd); - p.Do(mp3Buf); - p.Do(mp3BufSize); - p.Do(mp3PcmBuf); - p.Do(mp3BufPendingSize); - p.Do(mp3PcmBufSize); - p.Do(mp3InputFileReadPos); - p.Do(mp3InputBufWritePos); - p.Do(mp3InputBufSize); - p.Do(mp3InputFileSize); - p.Do(mp3DecodedBytes); - p.Do(mp3LoopNum); - p.Do(mp3MaxSamples); - p.Do(mp3Bitrate); - p.Do(mp3Channels); - p.Do(mp3SamplingRate); - p.Do(mp3Version); - p.DoClass(mediaengine); - p.DoMarker("Mp3Context"); - } - - u64 mp3StreamStart; - u64 mp3StreamEnd; - u64 mp3StreamPosition; - u32 mp3Buf; - int mp3BufSize; - int mp3BufPendingSize; - u32 mp3PcmBuf; - int mp3PcmBufSize; - - int mp3InputFileReadPos; - int mp3InputBufWritePos; - int mp3InputBufSize; - int mp3InputFileSize; - int mp3DecodedBytes; - int mp3LoopNum; - int mp3MaxSamples; - - int mp3Channels; - int mp3Bitrate; - int mp3SamplingRate; - int mp3Version; - - MediaEngine *mediaengine; -}; - struct StreamInfo { int type; int num; @@ -244,10 +186,7 @@ static bool isCurrentMpegAnalyzed; static bool fakeMode; static int actionPostPut; static std::map mpegMap; -static std::map mp3Map; -// TODO: Remove. static u32 lastMpegHandle = 0; -static u32 lastMp3Handle = 0; MpegContext *getMpegCtx(u32 mpegAddr) { u32 mpeg = Memory::Read_U32(mpegAddr); @@ -264,18 +203,6 @@ MpegContext *getMpegCtx(u32 mpegAddr) { return mpegMap[mpeg]; } -Mp3Context *getMp3Ctx(u32 mp3) { - if (mp3Map.find(mp3) == mp3Map.end()) - { - ERROR_LOG(HLE, "Bad mp3 handle %08x - using last one (%08x) instead", mp3, lastMp3Handle); - mp3 = lastMp3Handle; - } - - if (mp3Map.find(mp3) == mp3Map.end()) - return NULL; - return mp3Map[mp3]; -} - u32 getMpegHandle(u32 mpeg) { return Memory::Read_U32(mpeg); } @@ -1446,338 +1373,6 @@ int sceMpegGetUserdataAu(u32 mpeg, u32 streamUid, u32 auAddr, u32 resultAddr) return 0; } -/* MP3 */ -int sceMp3Decode(u32 mp3, u32 outPcmPtr) -{ - DEBUG_LOG(HLE, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - // Nothing to decode - if(ctx->mp3BufPendingSize == 0 || ctx->mp3StreamPosition >= ctx->mp3StreamEnd) { - if (ctx->mp3LoopNum == 0) { - return 0; - } else if (ctx->mp3LoopNum > 0) { - --ctx->mp3LoopNum; - } - } - - Memory::Memset(ctx->mp3PcmBuf, 0, ctx->mp3PcmBufSize); - Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); - - // TODO: Actually decode the data -#ifdef _DEBUG - char fileName[256]; - sprintf(fileName, "%lli.mp3", ctx->mp3StreamPosition); - - FILE * file = fopen(fileName, "wb"); - if(file) { - if(!Memory::IsValidAddress(ctx->mp3Buf)) { - ERROR_LOG(HLE, "sceMp3Decode mp3Buf %08X is not a valid address!", ctx->mp3Buf); - } - - u8 * ptr = Memory::GetPointer(ctx->mp3Buf); - fwrite(ptr, 1, ctx->mp3BufPendingSize, file); - - fclose(file); - } -#endif - - ctx->mp3StreamPosition += ctx->mp3BufPendingSize; - if(ctx->mp3StreamPosition > ctx->mp3StreamEnd) - ctx->mp3StreamPosition = ctx->mp3StreamEnd; - - // Reset the pending buffer size so the program will know that we need to buffer more data - ctx->mp3BufPendingSize = (ctx->mp3StreamPosition < ctx->mp3StreamEnd)?-1:0; - - return ctx->mp3PcmBufSize; -} - -int sceMp3ResetPlayPosition(u32 mp3) -{ - DEBUG_LOG(HLE, "SceMp3ResetPlayPosition(%08x)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - ctx->mp3StreamPosition = 0; - ctx->mp3BufPendingSize = -1; - return 0; -} - -int sceMp3CheckStreamDataNeeded(u32 mp3) -{ - DEBUG_LOG(HLE, "sceMp3CheckStreamDataNeeded(%08x)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return (ctx->mp3BufPendingSize < 0) && (ctx->mp3StreamPosition < ctx->mp3StreamEnd); -} - -u32 sceMp3ReserveMp3Handle(u32 mp3Addr) -{ - DEBUG_LOG(HLE, "sceMp3ReserveMp3Handle(%08x)", mp3Addr); - Mp3Context *ctx = new Mp3Context; - - memset(ctx, 0, sizeof(Mp3Context)); - - ctx->mp3StreamStart = Memory::Read_U64(mp3Addr); - ctx->mp3StreamEnd = Memory::Read_U64(mp3Addr+8); - ctx->mp3Buf = Memory::Read_U32(mp3Addr+16); - ctx->mp3BufSize = Memory::Read_U32(mp3Addr+20); - ctx->mp3PcmBuf = Memory::Read_U32(mp3Addr+24); - ctx->mp3PcmBufSize = Memory::Read_U32(mp3Addr+28); - - ctx->mp3StreamPosition = ctx->mp3StreamStart; - ctx->mp3BufPendingSize = -1; - ctx->mp3MaxSamples = ctx->mp3PcmBufSize / 4 ; - - /*ctx->mp3Channels = 2; - ctx->mp3Bitrate = 128; - ctx->mp3SamplingRate = 44100;*/ - - mp3Map[mp3Addr] = ctx; - return mp3Addr; -} - -int sceMp3InitResource() -{ - WARN_LOG(HLE, "UNIML: sceMp3InitResource"); - // Do nothing here - return 0; -} - -int sceMp3TermResource() -{ - WARN_LOG(HLE, "UNIML: sceMp3TermResource"); - // Do nothing here - return 0; -} - -int sceMp3Init(u32 mp3) -{ - DEBUG_LOG(HLE, "sceMp3Init(%08x)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - // Read in the header and swap the endian - int header = Memory::Read_U32(ctx->mp3Buf); - header = (header >> 24) | - ((header<<8) & 0x00FF0000) | - ((header>>8) & 0x0000FF00) | - (header << 24); - - int channels = ((header >> 6) & 0x3); - if(channels == 0 || channels == 1 || channels == 2) - ctx->mp3Channels = 2; - else if(channels == 3) - ctx->mp3Channels = 1; - else - ctx->mp3Channels = 0; - - // 0 == VBR - int bitrate = ((header >> 10) & 0x3); - if(bitrate < (int)ARRAY_SIZE(MP3_BITRATES)) - ctx->mp3Bitrate = MP3_BITRATES[bitrate]; - else - ctx->mp3Bitrate = -1; - - int samplerate = ((header >> 12) & 0x3); - if (samplerate == 0) { - ctx->mp3SamplingRate = 44100; - } else if (samplerate == 1) { - ctx->mp3SamplingRate = 48000; - } else if (samplerate == 2) { - ctx->mp3SamplingRate = 32000; - } else { - ctx->mp3SamplingRate = 0; - } - - ctx->mp3Version = ((header >> 19) & 0x3); - - return 0; -} - -int sceMp3GetLoopNum(u32 mp3) -{ - DEBUG_LOG(HLE, "sceMp3GetLoopNum(%08x)", mp3); - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3LoopNum; -} - -int sceMp3GetMaxOutputSample(u32 mp3) -{ - DEBUG_LOG(HLE, "sceMp3GetMaxOutputSample(%08x)", mp3); - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3MaxSamples; -} - -int sceMp3NotifyAddStreamData(u32 mp3, int size) { - DEBUG_LOG(HLE, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - ctx->mp3BufPendingSize = size; - - return 0; -} -int sceMp3GetSumDecodedSample(u32 mp3) { - DEBUG_LOG(HLE, "UNIMPL: sceMp3GetSumDecodedSample(%08X)", mp3); - return 0; -} -int sceMp3SetLoopNum(u32 mp3, int loop) { - DEBUG_LOG(HLE, "sceMp3SetLoopNum(%08X, %i)", mp3, loop); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - ctx->mp3LoopNum = loop; - - return 0; -} -int sceMp3GetMp3ChannelNum(u32 mp3) { - DEBUG_LOG(HLE, "sceMp3GetMp3ChannelNum(%08X)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3Channels; -} -int sceMp3GetBitRate(u32 mp3) { - DEBUG_LOG(HLE, "sceMp3GetBitRate(%08X)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3Bitrate; -} -int sceMp3GetSamplingRate(u32 mp3) { - DEBUG_LOG(HLE, "sceMp3GetSamplingRate(%08X)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3SamplingRate; -} -int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) { - DEBUG_LOG(HLE, "HACK: sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - if(Memory::IsValidAddress(dstPtr)) - Memory::Write_U32(ctx->mp3Buf, dstPtr); - if(Memory::IsValidAddress(towritePtr)) - Memory::Write_U32(ctx->mp3BufSize, towritePtr); - if(Memory::IsValidAddress(srcposPtr)) - Memory::Write_U32((u32)ctx->mp3StreamPosition, srcposPtr); - - return 0; -} -int sceMp3ReleaseMp3Handle(u32 mp3) { - DEBUG_LOG(HLE, "sceMp3ReleaseMp3Handle(%08X)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - mp3Map.erase(mp3Map.find(mp3)); - - delete ctx; - - return 0; -} - -u32 sceMp3EndEntry() -{ - DEBUG_LOG(HLE, "UNIMPL sceMp3StartEntry(.)"); - return 0; -} - -u32 sceMp3StartEntry() -{ - DEBUG_LOG(HLE, "UNIMPL sceMp3StartEntry(.)"); - return 0; -} - -u32 sceMp3GetFrameNum(u32 mp3) -{ - DEBUG_LOG(HLE, "UNIMPL sceMp3GetFrameNum(%08x)", mp3); - return 0; -} - -u32 sceMp3GetVersion(u32 mp3) -{ - DEBUG_LOG(HLE, "sceMp3GetVersion(%08x)", mp3); - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) - { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - - return ctx->mp3Version; -} - const HLEFunction sceMpeg[] = { {0xe1ce83a7,WrapI_UUUU,"sceMpegGetAtracAu"}, @@ -1828,37 +1423,7 @@ const HLEFunction sceMpeg[] = {0x01977054,WrapI_UUUU,"sceMpegGetUserdataAu"}, }; -const HLEFunction sceMp3[] = -{ - {0x07EC321A,WrapU_U,"sceMp3ReserveMp3Handle"}, - {0x0DB149F4,WrapI_UI,"sceMp3NotifyAddStreamData"}, - {0x2A368661,WrapI_U,"sceMp3ResetPlayPosition"}, - {0x354D27EA,WrapI_U,"sceMp3GetSumDecodedSample"}, - {0x35750070,WrapI_V,"sceMp3InitResource"}, - {0x3C2FA058,WrapI_V,"sceMp3TermResource"}, - {0x3CEF484F,WrapI_UI,"sceMp3SetLoopNum"}, - {0x44E07129,WrapI_U,"sceMp3Init"}, - {0x732B042A,WrapU_V,"sceMp3EndEntry"}, - {0x7F696782,WrapI_U,"sceMp3GetMp3ChannelNum"}, - {0x87677E40,WrapI_U,"sceMp3GetBitRate"}, - {0x87C263D1,WrapI_U,"sceMp3GetMaxOutputSample"}, - {0x8AB81558,WrapU_V,"sceMp3StartEntry"}, - {0x8F450998,WrapI_U,"sceMp3GetSamplingRate"}, - {0xA703FE0F,WrapI_UUUU,"sceMp3GetInfoToAddStreamData"}, - {0xD021C0FB,WrapI_UU,"sceMp3Decode"}, - {0xD0A56296,WrapI_U,"sceMp3CheckStreamDataNeeded"}, - {0xD8F54A51,WrapI_U,"sceMp3GetLoopNum"}, - {0xF5478233,WrapI_U,"sceMp3ReleaseMp3Handle"}, - {0xAE6D2027,WrapU_U,"sceMp3GetVersion"}, - {0x3548AEC8,WrapU_U,"sceMp3GetFrameNum"}, -}; - void Register_sceMpeg() { RegisterModule("sceMpeg", ARRAY_SIZE(sceMpeg), sceMpeg); } - -void Register_sceMp3() -{ - RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3); -} diff --git a/Core/HLE/sceMpeg.h b/Core/HLE/sceMpeg.h index a5971dd912..9ac720bde9 100644 --- a/Core/HLE/sceMpeg.h +++ b/Core/HLE/sceMpeg.h @@ -95,5 +95,4 @@ void __MpegInit(bool useMediaEngine_); void __MpegDoState(PointerWrap &p); void __MpegShutdown(); -void Register_sceMpeg(); -void Register_sceMp3(); \ No newline at end of file +void Register_sceMpeg(); \ No newline at end of file diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 95d75ea0bc..342ebdf6b7 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -216,6 +216,7 @@ LOCAL_SRC_FILES := \ $(SRC)/Core/HLE/sceKernelVTimer.cpp \ $(SRC)/Core/HLE/sceMpeg.cpp \ $(SRC)/Core/HLE/sceMp4.cpp \ + $(SRC)/Core/HLE/sceMp3.cpp \ $(SRC)/Core/HLE/sceNet.cpp \ $(SRC)/Core/HLE/sceOpenPSID.cpp \ $(SRC)/Core/HLE/sceP3da.cpp \