mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-03 12:12:06 +00:00
Merge pull request #1698 from raven02/mp3-pre
Separate sceMp3 from sceMpeg
This commit is contained in:
commit
7957cff30b
@ -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
|
||||
|
@ -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
|
||||
|
@ -211,6 +211,7 @@
|
||||
<ClCompile Include="HLE\scePspNpDrm_user.cpp" />
|
||||
<ClCompile Include="HLE\sceP3da.cpp" />
|
||||
<ClCompile Include="HLE\sceMp4.cpp" />
|
||||
<ClCompile Include="HLE\sceMp3.cpp" />
|
||||
<ClCompile Include="HLE\sceGameUpdate.cpp" />
|
||||
<ClCompile Include="HLE\sceRtc.cpp" />
|
||||
<ClCompile Include="HLE\sceSas.cpp" />
|
||||
@ -383,6 +384,7 @@
|
||||
<ClInclude Include="HLE\scePspNpDrm_user.h" />
|
||||
<ClInclude Include="HLE\sceP3da.h" />
|
||||
<ClInclude Include="HLE\sceMp4.h" />
|
||||
<ClInclude Include="HLE\sceMp3.h" />
|
||||
<ClInclude Include="HLE\sceGameUpdate.h" />
|
||||
<ClInclude Include="HLE\sceRtc.h" />
|
||||
<ClInclude Include="HLE\sceSas.h" />
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "sceGameUpdate.h"
|
||||
#include "sceDeflt.h"
|
||||
#include "sceMp4.h"
|
||||
#include "sceMp3.h"
|
||||
#include "scePauth.h"
|
||||
#include "sceNp.h"
|
||||
|
||||
|
414
Core/HLE/sceMp3.cpp
Normal file
414
Core/HLE/sceMp3.cpp
Normal file
@ -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 <map>
|
||||
#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<u32, Mp3Context *> 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>,"sceMp3ReserveMp3Handle"},
|
||||
{0x0DB149F4,WrapI_UI<sceMp3NotifyAddStreamData>,"sceMp3NotifyAddStreamData"},
|
||||
{0x2A368661,WrapI_U<sceMp3ResetPlayPosition>,"sceMp3ResetPlayPosition"},
|
||||
{0x354D27EA,WrapI_U<sceMp3GetSumDecodedSample>,"sceMp3GetSumDecodedSample"},
|
||||
{0x35750070,WrapI_V<sceMp3InitResource>,"sceMp3InitResource"},
|
||||
{0x3C2FA058,WrapI_V<sceMp3TermResource>,"sceMp3TermResource"},
|
||||
{0x3CEF484F,WrapI_UI<sceMp3SetLoopNum>,"sceMp3SetLoopNum"},
|
||||
{0x44E07129,WrapI_U<sceMp3Init>,"sceMp3Init"},
|
||||
{0x732B042A,WrapU_V<sceMp3EndEntry>,"sceMp3EndEntry"},
|
||||
{0x7F696782,WrapI_U<sceMp3GetMp3ChannelNum>,"sceMp3GetMp3ChannelNum"},
|
||||
{0x87677E40,WrapI_U<sceMp3GetBitRate>,"sceMp3GetBitRate"},
|
||||
{0x87C263D1,WrapI_U<sceMp3GetMaxOutputSample>,"sceMp3GetMaxOutputSample"},
|
||||
{0x8AB81558,WrapU_V<sceMp3StartEntry>,"sceMp3StartEntry"},
|
||||
{0x8F450998,WrapI_U<sceMp3GetSamplingRate>,"sceMp3GetSamplingRate"},
|
||||
{0xA703FE0F,WrapI_UUUU<sceMp3GetInfoToAddStreamData>,"sceMp3GetInfoToAddStreamData"},
|
||||
{0xD021C0FB,WrapI_UU<sceMp3Decode>,"sceMp3Decode"},
|
||||
{0xD0A56296,WrapI_U<sceMp3CheckStreamDataNeeded>,"sceMp3CheckStreamDataNeeded"},
|
||||
{0xD8F54A51,WrapI_U<sceMp3GetLoopNum>,"sceMp3GetLoopNum"},
|
||||
{0xF5478233,WrapI_U<sceMp3ReleaseMp3Handle>,"sceMp3ReleaseMp3Handle"},
|
||||
{0xAE6D2027,WrapU_U<sceMp3GetVersion>,"sceMp3GetVersion"},
|
||||
{0x3548AEC8,WrapU_U<sceMp3GetFrameNum>,"sceMp3GetFrameNum"},
|
||||
};
|
||||
|
||||
void Register_sceMp3()
|
||||
{
|
||||
RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3);
|
||||
}
|
22
Core/HLE/sceMp3.h
Normal file
22
Core/HLE/sceMp3.h
Normal file
@ -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();
|
@ -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<u32, MpegContext *> mpegMap;
|
||||
static std::map<u32, Mp3Context *> 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>,"sceMpegGetAtracAu"},
|
||||
@ -1828,37 +1423,7 @@ const HLEFunction sceMpeg[] =
|
||||
{0x01977054,WrapI_UUUU<sceMpegGetUserdataAu>,"sceMpegGetUserdataAu"},
|
||||
};
|
||||
|
||||
const HLEFunction sceMp3[] =
|
||||
{
|
||||
{0x07EC321A,WrapU_U<sceMp3ReserveMp3Handle>,"sceMp3ReserveMp3Handle"},
|
||||
{0x0DB149F4,WrapI_UI<sceMp3NotifyAddStreamData>,"sceMp3NotifyAddStreamData"},
|
||||
{0x2A368661,WrapI_U<sceMp3ResetPlayPosition>,"sceMp3ResetPlayPosition"},
|
||||
{0x354D27EA,WrapI_U<sceMp3GetSumDecodedSample>,"sceMp3GetSumDecodedSample"},
|
||||
{0x35750070,WrapI_V<sceMp3InitResource>,"sceMp3InitResource"},
|
||||
{0x3C2FA058,WrapI_V<sceMp3TermResource>,"sceMp3TermResource"},
|
||||
{0x3CEF484F,WrapI_UI<sceMp3SetLoopNum>,"sceMp3SetLoopNum"},
|
||||
{0x44E07129,WrapI_U<sceMp3Init>,"sceMp3Init"},
|
||||
{0x732B042A,WrapU_V<sceMp3EndEntry>,"sceMp3EndEntry"},
|
||||
{0x7F696782,WrapI_U<sceMp3GetMp3ChannelNum>,"sceMp3GetMp3ChannelNum"},
|
||||
{0x87677E40,WrapI_U<sceMp3GetBitRate>,"sceMp3GetBitRate"},
|
||||
{0x87C263D1,WrapI_U<sceMp3GetMaxOutputSample>,"sceMp3GetMaxOutputSample"},
|
||||
{0x8AB81558,WrapU_V<sceMp3StartEntry>,"sceMp3StartEntry"},
|
||||
{0x8F450998,WrapI_U<sceMp3GetSamplingRate>,"sceMp3GetSamplingRate"},
|
||||
{0xA703FE0F,WrapI_UUUU<sceMp3GetInfoToAddStreamData>,"sceMp3GetInfoToAddStreamData"},
|
||||
{0xD021C0FB,WrapI_UU<sceMp3Decode>,"sceMp3Decode"},
|
||||
{0xD0A56296,WrapI_U<sceMp3CheckStreamDataNeeded>,"sceMp3CheckStreamDataNeeded"},
|
||||
{0xD8F54A51,WrapI_U<sceMp3GetLoopNum>,"sceMp3GetLoopNum"},
|
||||
{0xF5478233,WrapI_U<sceMp3ReleaseMp3Handle>,"sceMp3ReleaseMp3Handle"},
|
||||
{0xAE6D2027,WrapU_U<sceMp3GetVersion>,"sceMp3GetVersion"},
|
||||
{0x3548AEC8,WrapU_U<sceMp3GetFrameNum>,"sceMp3GetFrameNum"},
|
||||
};
|
||||
|
||||
void Register_sceMpeg()
|
||||
{
|
||||
RegisterModule("sceMpeg", ARRAY_SIZE(sceMpeg), sceMpeg);
|
||||
}
|
||||
|
||||
void Register_sceMp3()
|
||||
{
|
||||
RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3);
|
||||
}
|
||||
|
@ -95,5 +95,4 @@ void __MpegInit(bool useMediaEngine_);
|
||||
void __MpegDoState(PointerWrap &p);
|
||||
void __MpegShutdown();
|
||||
|
||||
void Register_sceMpeg();
|
||||
void Register_sceMp3();
|
||||
void Register_sceMpeg();
|
@ -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 \
|
||||
|
Loading…
x
Reference in New Issue
Block a user