mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Merge branch 'master' of github.com:hrydgard/ppsspp
Conflicts: UI/GameInfoCache.h
This commit is contained in:
commit
533541615f
@ -477,6 +477,9 @@ elseif(SDL_FOUND)
|
||||
elseif(PANDORA OR MAEMO)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} pthread EGL X11)
|
||||
endif()
|
||||
# FFMPEG
|
||||
add_definitions(-DUSE_FFMPEG)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} avformat avcodec swresample swscale)
|
||||
set(TargetBin PPSSPPSDL)
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find SDL. Failing.")
|
||||
@ -758,6 +761,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
||||
Core/HLE/sceAtrac.cpp
|
||||
Core/HLE/sceAtrac.h
|
||||
Core/HLE/sceAudio.cpp
|
||||
Core/HLE/sceAudioCodec.cpp
|
||||
Core/HLE/sceAudioCodec.h
|
||||
Core/HLE/sceAudio.h
|
||||
Core/HLE/sceChnnlsv.cpp
|
||||
Core/HLE/sceChnnlsv.h
|
||||
|
@ -72,6 +72,7 @@ set(SRCS
|
||||
HLE/sceParseUri.cpp
|
||||
HLE/sceParseHttp.cpp
|
||||
HLE/sceVaudio.cpp
|
||||
HLE/sceAudiocodec.cpp
|
||||
HW/MemoryStick.cpp
|
||||
HW/MediaEngine.cpp
|
||||
HW/SasAudio.cpp
|
||||
|
@ -188,6 +188,7 @@
|
||||
<ClCompile Include="HLE\HLETables.cpp" />
|
||||
<ClCompile Include="HLE\sceAtrac.cpp" />
|
||||
<ClCompile Include="HLE\sceAudio.cpp" />
|
||||
<ClCompile Include="HLE\sceAudiocodec.cpp" />
|
||||
<ClCompile Include="HLE\sceChnnlsv.cpp" />
|
||||
<ClCompile Include="HLE\sceCtrl.cpp" />
|
||||
<ClCompile Include="HLE\sceDeflt.cpp" />
|
||||
@ -368,6 +369,7 @@
|
||||
<ClInclude Include="HLE\HLETables.h" />
|
||||
<ClInclude Include="HLE\sceAtrac.h" />
|
||||
<ClInclude Include="HLE\sceAudio.h" />
|
||||
<ClInclude Include="HLE\sceAudiocodec.h" />
|
||||
<ClInclude Include="HLE\sceCtrl.h" />
|
||||
<ClInclude Include="HLE\sceChnnlsv.h" />
|
||||
<ClInclude Include="HLE\sceDeflt.h" />
|
||||
|
@ -433,6 +433,9 @@
|
||||
<ClCompile Include="HW\MpegDemux.cpp">
|
||||
<Filter>HW</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HLE\sceAudiocodec.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -801,6 +804,9 @@
|
||||
<ClInclude Include="HW\MpegDemux.h">
|
||||
<Filter>HW</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HLE\sceAudiocodec.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "sceNp.h"
|
||||
#include "sceMd5.h"
|
||||
#include "sceJpeg.h"
|
||||
#include "sceAudiocodec.h"
|
||||
|
||||
#define N(s) s
|
||||
|
||||
@ -269,6 +270,7 @@ void RegisterAllModules() {
|
||||
Register_sceNpAuth();
|
||||
Register_sceMd5();
|
||||
Register_sceJpeg();
|
||||
Register_sceAudiocodec();
|
||||
|
||||
for (int i = 0; i < numModules; i++)
|
||||
{
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include "sceKernel.h"
|
||||
#include "sceUtility.h"
|
||||
#include "sceKernelMemory.h"
|
||||
#include "sceAtrac.h"
|
||||
|
||||
|
||||
#define ATRAC_ERROR_API_FAIL 0x80630002
|
||||
@ -113,6 +115,7 @@ struct Atrac {
|
||||
pFrame = 0;
|
||||
#endif // USE_FFMPEG
|
||||
decoder_context = 0;
|
||||
atracContext = 0;
|
||||
sampleQueue.clear();
|
||||
}
|
||||
|
||||
@ -131,6 +134,9 @@ struct Atrac {
|
||||
|
||||
Atrac3plus_Decoder::CloseContext(&decoder_context);
|
||||
sampleQueue.clear();
|
||||
|
||||
if (atracContext.Valid())
|
||||
kernelMemory.Free(atracContext.ptr);
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p) {
|
||||
@ -172,6 +178,11 @@ struct Atrac {
|
||||
p.Do(loopEndSample);
|
||||
p.Do(loopNum);
|
||||
|
||||
// Is NULL okay for this?
|
||||
if (p.mode == p.MODE_READ)
|
||||
decoder_context = 0;
|
||||
p.Do(atracContext);
|
||||
|
||||
p.DoMarker("Atrac");
|
||||
}
|
||||
|
||||
@ -230,6 +241,8 @@ struct Atrac {
|
||||
Atrac3plus_Decoder::BufferQueue sampleQueue;
|
||||
void* decoder_context;
|
||||
|
||||
PSPPointer<SceAtracId> atracContext;
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
AVFormatContext *pFormatCtx;
|
||||
AVIOContext *pAVIOCtx;
|
||||
@ -483,18 +496,17 @@ u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishFlagAddr, u32 remainAddr)
|
||||
u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int *remains)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceAtracDecodeData(%i, %08x, %08x, %08x, %08x)", atracID, outAddr, numSamplesAddr, finishFlagAddr, remainAddr);
|
||||
Atrac *atrac = getAtrac(atracID);
|
||||
|
||||
u32 ret = 0;
|
||||
if (atrac != NULL) {
|
||||
// We already passed the end - return an error (many games check for this.)
|
||||
if (atrac->currentSample >= atrac->endSample && atrac->loopNum == 0) {
|
||||
Memory::Write_U32(0, numSamplesAddr);
|
||||
Memory::Write_U32(1, finishFlagAddr);
|
||||
Memory::Write_U32(0, remainAddr);
|
||||
*SamplesNum = 0;
|
||||
*finish = 1;
|
||||
*remains = 0;
|
||||
ret = ATRAC_ERROR_ALL_DATA_DECODED;
|
||||
} else {
|
||||
// TODO: This isn't at all right, but at least it makes the music "last" some time.
|
||||
@ -520,7 +532,7 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
||||
// got a frame
|
||||
int decoded = av_samples_get_buffer_size(NULL, atrac->pFrame->channels,
|
||||
atrac->pFrame->nb_samples, (AVSampleFormat)atrac->pFrame->format, 1);
|
||||
u8* out = Memory::GetPointer(outAddr);
|
||||
u8* out = outbuf;
|
||||
numSamples = atrac->pFrame->nb_samples;
|
||||
avret = swr_convert(atrac->pSwrCtx, &out, atrac->pFrame->nb_samples,
|
||||
(const u8**)atrac->pFrame->extended_data, atrac->pFrame->nb_samples);
|
||||
@ -547,11 +559,10 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
||||
inbytes = std::min(inbytes, (int)atrac->atracBytesPerFrame);
|
||||
if (inbytes > 0 && inbytes == atrac->atracBytesPerFrame) {
|
||||
Atrac3plus_Decoder::Decode(atrac->decoder_context, atrac->data_buf + atrac->decodePos, inbytes, &decodebytes, buf);
|
||||
DEBUG_LOG(HLE, "atracID: %i decodebytes: %i outAddr: %08x", atracID, decodebytes, outAddr);
|
||||
atrac->sampleQueue.push(buf, decodebytes);
|
||||
}
|
||||
}
|
||||
s16* out = (s16*)Memory::GetPointer(outAddr);
|
||||
s16* out = (s16*)outbuf;
|
||||
memset(out, 0, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
|
||||
int gotsize = atrac->sampleQueue.pop_front(buf, ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels);
|
||||
numSamples = gotsize / sizeof(s16) / atrac->atracChannels;
|
||||
@ -569,7 +580,7 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
||||
} else
|
||||
{
|
||||
numSamples = atrac->endSample - atrac->currentSample;
|
||||
int atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
if (atrac->currentSample >= atrac->endSample) {
|
||||
numSamples = 0;
|
||||
} else if (numSamples > atracSamplesPerFrame) {
|
||||
@ -579,10 +590,10 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
||||
if (numSamples == 0 && (atrac->loopNum != 0)) {
|
||||
numSamples = atracSamplesPerFrame;
|
||||
}
|
||||
Memory::Memset(outAddr, 0, numSamples * sizeof(s16) * atrac->atracOutputChannels);
|
||||
memset(outbuf, 0, numSamples * sizeof(s16) * atrac->atracOutputChannels);
|
||||
}
|
||||
|
||||
Memory::Write_U32(numSamples, numSamplesAddr);
|
||||
*SamplesNum = numSamples;
|
||||
// update current sample and decodePos
|
||||
atrac->currentSample += numSamples;
|
||||
atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample);
|
||||
@ -597,23 +608,33 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
|
||||
(numSamples == 0 && atrac->first.size >= atrac->first.filesize))
|
||||
finishFlag = 1;
|
||||
|
||||
Memory::Write_U32(finishFlag, finishFlagAddr);
|
||||
int remains = atrac->getRemainFrames();
|
||||
Memory::Write_U32(remains, remainAddr);
|
||||
*finish = finishFlag;
|
||||
*remains = atrac->getRemainFrames();
|
||||
}
|
||||
// TODO: Can probably remove this after we validate no wrong ids?
|
||||
} else {
|
||||
Memory::Write_U16(0, outAddr); // Write a single 16-bit stereo
|
||||
Memory::Write_U16(0, outAddr + 2);
|
||||
|
||||
Memory::Write_U32(1, numSamplesAddr);
|
||||
Memory::Write_U32(1, finishFlagAddr); // Lie that decoding is finished
|
||||
Memory::Write_U32(-1, remainAddr); // Lie that decoding is finished
|
||||
memset(outbuf, 0, ATRAC3_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
|
||||
*SamplesNum = ATRAC3_MAX_SAMPLES;
|
||||
*finish = 1;
|
||||
*remains = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishFlagAddr, u32 remainAddr)
|
||||
{
|
||||
DEBUG_LOG(HLE, "sceAtracDecodeData(%i, %08x, %08x, %08x, %08x)", atracID, outAddr, numSamplesAddr, finishFlagAddr, remainAddr);
|
||||
u32 numSamples = 0;
|
||||
u32 finish = 0;
|
||||
int remains = 0;
|
||||
int ret = _AtracDecodeData(atracID, Memory::GetPointer(outAddr), &numSamples, &finish, &remains);
|
||||
Memory::Write_U32(numSamples, numSamplesAddr);
|
||||
Memory::Write_U32(finish, finishFlagAddr);
|
||||
Memory::Write_U32(remains, remainAddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 sceAtracEndEntry()
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL sceAtracEndEntry()");
|
||||
@ -756,7 +777,7 @@ u32 sceAtracGetNextSample(int atracID, u32 outNAddr)
|
||||
Memory::Write_U32(0, outNAddr);
|
||||
} else {
|
||||
u32 numSamples = atrac->endSample - atrac->currentSample;
|
||||
int atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
if (numSamples > atracSamplesPerFrame)
|
||||
numSamples = atracSamplesPerFrame;
|
||||
if (Memory::IsValidAddress(outNAddr))
|
||||
@ -896,6 +917,39 @@ int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence)
|
||||
|
||||
#endif // USE_FFMPEG
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
int __AtracUpdateOutputMode(Atrac *atrac, int wanted_channels) {
|
||||
if (atrac->pSwrCtx && atrac->atracOutputChannels == wanted_channels)
|
||||
return 0;
|
||||
atrac->atracOutputChannels = wanted_channels;
|
||||
int64_t wanted_channel_layout = av_get_default_channel_layout(wanted_channels);
|
||||
int64_t dec_channel_layout = av_get_default_channel_layout(atrac->atracChannels);
|
||||
|
||||
atrac->pSwrCtx =
|
||||
swr_alloc_set_opts
|
||||
(
|
||||
atrac->pSwrCtx,
|
||||
wanted_channel_layout,
|
||||
AV_SAMPLE_FMT_S16,
|
||||
atrac->pCodecCtx->sample_rate,
|
||||
dec_channel_layout,
|
||||
atrac->pCodecCtx->sample_fmt,
|
||||
atrac->pCodecCtx->sample_rate,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (!atrac->pSwrCtx) {
|
||||
ERROR_LOG(HLE, "swr_alloc_set_opts: Could not allocate resampler context");
|
||||
return -1;
|
||||
}
|
||||
if (swr_init(atrac->pSwrCtx) < 0) {
|
||||
ERROR_LOG(HLE, "swr_init: Failed to initialize the resampling context");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // USE_FFMPEG
|
||||
|
||||
int __AtracSetContext(Atrac *atrac)
|
||||
{
|
||||
if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
|
||||
@ -938,31 +992,8 @@ int __AtracSetContext(Atrac *atrac)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int wanted_channels = atrac->atracOutputChannels;
|
||||
int64_t wanted_channel_layout = av_get_default_channel_layout(wanted_channels);
|
||||
int64_t dec_channel_layout = av_get_default_channel_layout(atrac->atracChannels);
|
||||
|
||||
atrac->pSwrCtx =
|
||||
swr_alloc_set_opts
|
||||
(
|
||||
NULL,
|
||||
wanted_channel_layout,
|
||||
AV_SAMPLE_FMT_S16,
|
||||
atrac->pCodecCtx->sample_rate,
|
||||
dec_channel_layout,
|
||||
atrac->pCodecCtx->sample_fmt,
|
||||
atrac->pCodecCtx->sample_rate,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (!atrac->pSwrCtx) {
|
||||
ERROR_LOG(HLE, "swr_alloc_set_opts: Could not allocate resampler context %d", ret);
|
||||
return -1;
|
||||
}
|
||||
if ((ret = swr_init(atrac->pSwrCtx)) < 0) {
|
||||
ERROR_LOG(HLE, "swr_init: Failed to initialize the resampling context %d", ret);
|
||||
return -1;
|
||||
}
|
||||
if ((ret = __AtracUpdateOutputMode(atrac, atrac->atracOutputChannels)) < 0)
|
||||
return ret;
|
||||
|
||||
// alloc audio frame
|
||||
atrac->pFrame = avcodec_alloc_frame();
|
||||
@ -1232,15 +1263,67 @@ int sceAtracSetAA3DataAndGetID(u32 buffer, int bufferSize, int fileSize, u32 met
|
||||
return createAtrac(atrac);
|
||||
}
|
||||
|
||||
int _AtracGetIDByContext(u32 contextAddr) {
|
||||
int atracID = (int)Memory::Read_U32(contextAddr + 0xfc);
|
||||
#ifdef USE_FFMPEG
|
||||
Atrac *atrac = getAtrac(atracID);
|
||||
if (atrac)
|
||||
__AtracUpdateOutputMode(atrac, 1);
|
||||
#endif // USE_FFMPEG
|
||||
return atracID;
|
||||
}
|
||||
|
||||
void _AtracGenarateContext(Atrac *atrac, SceAtracId *context) {
|
||||
context->info.buffer = atrac->first.addr;
|
||||
context->info.bufferByte = atrac->atracBufSize;
|
||||
context->info.codec = atrac->codeType;
|
||||
context->info.loopNum = atrac->loopNum;
|
||||
context->info.loopStart = atrac->loopStartSample > 0 ? atrac->loopStartSample : 0;
|
||||
context->info.loopEnd = atrac->loopEndSample > 0 ? atrac->loopEndSample : 0;
|
||||
if (atrac->first.size >= atrac->first.fileoffset) {
|
||||
// state 2, all data loaded
|
||||
context->info.state = 2;
|
||||
} else if (atrac->loopinfoNum == 0) {
|
||||
// state 3, lack some data, no loop info
|
||||
context->info.state = 3;
|
||||
} else {
|
||||
// state 6, lack some data, has loop info
|
||||
context->info.state = 6;
|
||||
}
|
||||
context->info.samplesPerChan = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES);
|
||||
context->info.sampleSize = atrac->atracBytesPerFrame;
|
||||
context->info.numChan = atrac->atracChannels;
|
||||
context->info.dataOff = atrac->firstSampleoffset;
|
||||
context->info.endSample = atrac->endSample;
|
||||
context->info.dataEnd = atrac->first.filesize;
|
||||
context->info.curOff = atrac->first.size;
|
||||
context->info.streamDataByte = atrac->first.size - atrac->firstSampleoffset;
|
||||
|
||||
u8* buf = (u8*)context;
|
||||
*(u32*)(buf + 0xfc) = atrac->atracID;
|
||||
}
|
||||
|
||||
int _sceAtracGetContextAddress(int atracID)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL _sceAtracGetContextAddress(%i)", atracID);
|
||||
Atrac *atrac = getAtrac(atracID);
|
||||
if (!atrac) {
|
||||
// Sol Trigger requires return -1 otherwise hangup .
|
||||
return -1;
|
||||
ERROR_LOG(HLE, "_sceAtracGetContextAddress(%i): bad atrac id", atracID);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
if (!atrac->atracContext.Valid()) {
|
||||
// allocate a new atracContext
|
||||
u32 contextsize = 256;
|
||||
atrac->atracContext = kernelMemory.Alloc(contextsize, false, "Atrac Context");
|
||||
if (atrac->atracContext.Valid())
|
||||
Memory::Memset(atrac->atracContext.ptr, 0, 256);
|
||||
|
||||
WARN_LOG(HLE, "%08x=_sceAtracGetContextAddress(%i): allocated new context", atrac->atracContext.ptr, atracID);
|
||||
}
|
||||
else
|
||||
WARN_LOG(HLE, "%08x=_sceAtracGetContextAddress(%i)", atrac->atracContext.ptr, atracID);
|
||||
if (atrac->atracContext.Valid())
|
||||
_AtracGenarateContext(atrac, atrac->atracContext);
|
||||
return atrac->atracContext.ptr;
|
||||
}
|
||||
|
||||
static u8 at3Header[] ={0x52,0x49,0x46,0x46,0x3b,0xbe,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x20,0x00,0x00,0x00,0x70,0x02,0x02,0x00,0x44,0xac,0x00,0x00,0x4d,0x20,0x00,0x00,0xc0,0x00,0x00,0x00,0x0e,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x64,0x61,0x74,0x61,0xc0,0xbd,0x00,0x00};
|
||||
|
@ -17,9 +17,54 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sceAudiocodec.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
void Register_sceAtrac3plus();
|
||||
void __AtracInit();
|
||||
void __AtracDoState(PointerWrap &p);
|
||||
void __AtracShutdown();
|
||||
void __AtracShutdown();
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 decodePos; // 0
|
||||
u32 endSample; // 4
|
||||
u32 loopStart; // 8
|
||||
u32 loopEnd; // 12
|
||||
int samplesPerChan; // 16
|
||||
char numFrame; // 20
|
||||
// 2: all the stream data on the buffer
|
||||
// 6: looping -> second buffer needed
|
||||
char state; // 21
|
||||
char unk22;
|
||||
char numChan; // 23
|
||||
u16 sampleSize; // 24
|
||||
u16 codec; // 26
|
||||
u32 dataOff; // 28
|
||||
u32 curOff; // 32
|
||||
u32 dataEnd; // 36
|
||||
int loopNum; // 40
|
||||
u32 streamDataByte; // 44
|
||||
u32 unk48;
|
||||
u32 unk52;
|
||||
u32 buffer; // 56
|
||||
u32 secondBuffer; // 60
|
||||
u32 bufferByte; // 64
|
||||
u32 secondBufferByte; // 68
|
||||
// make sure the size is 128
|
||||
u8 unk[56];
|
||||
} SceAtracIdInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// size 128
|
||||
SceAudiocodecCodec codec;
|
||||
// size 128
|
||||
SceAtracIdInfo info;
|
||||
} SceAtracId;
|
||||
|
||||
// provide some decoder interface
|
||||
|
||||
u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int *remains);
|
||||
int _AtracGetIDByContext(u32 contextAddr);
|
45
Core/HLE/sceAudiocodec.cpp
Normal file
45
Core/HLE/sceAudiocodec.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// 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 "Core/HLE/HLE.h"
|
||||
|
||||
#include "sceAudiocodec.h"
|
||||
#include "Core/Reporting.h"
|
||||
|
||||
int sceAudiocodecInit(u32 audioCodec, int codeType) {
|
||||
ERROR_LOG_REPORT(HLE, "UNIMPL sceAudiocodecInit(%08x, %x)", audioCodec, codeType);
|
||||
return 0;
|
||||
}
|
||||
int sceAudiocodecDecode(u32 audioCodec, int codeType) {
|
||||
ERROR_LOG_REPORT(HLE, "UNIMPL sceAudiocodecDecode(%08x, %x)", audioCodec, codeType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceAudiocodec[] =
|
||||
{
|
||||
{0x70A703F8, WrapI_UI<sceAudiocodecDecode>, "sceAudiocodecDecode"},
|
||||
{0x5B37EB1D, WrapI_UI<sceAudiocodecInit>, "sceAudiocodecInit"},
|
||||
{0x8ACA11D5, 0, "sceAudiocodecGetInfo"},
|
||||
{0x3A20A200, 0, "sceAudiocodecGetEDRAM"},
|
||||
{0x29681260, 0, "sceAudiocodecReleaseEDRAM"},
|
||||
{0x9D3F790C, 0, "sceAudiocodeCheckNeedMem"},
|
||||
};
|
||||
|
||||
void Register_sceAudiocodec()
|
||||
{
|
||||
RegisterModule("sceAudiocodec", ARRAY_SIZE(sceAudiocodec), sceAudiocodec);
|
||||
}
|
59
Core/HLE/sceAudiocodec.h
Normal file
59
Core/HLE/sceAudiocodec.h
Normal file
@ -0,0 +1,59 @@
|
||||
// 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
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s32 unk0;
|
||||
s32 unk4;
|
||||
s32 err; // 8
|
||||
s32 edramAddr; // 12
|
||||
s32 neededMem; // 16
|
||||
s32 unk20;
|
||||
u32 inBuf; // 24
|
||||
s32 unk28;
|
||||
u32 outBuf; // 32
|
||||
s32 unk36;
|
||||
s8 unk40;
|
||||
s8 unk41;
|
||||
s8 unk42;
|
||||
s8 unk43;
|
||||
s8 unk44;
|
||||
s8 unk45;
|
||||
s8 unk46;
|
||||
s8 unk47;
|
||||
s32 unk48;
|
||||
s32 unk52;
|
||||
s32 unk56;
|
||||
s32 unk60;
|
||||
s32 unk64;
|
||||
s32 unk68;
|
||||
s32 unk72;
|
||||
s32 unk76;
|
||||
s32 unk80;
|
||||
s32 unk84;
|
||||
s32 unk88;
|
||||
s32 unk92;
|
||||
s32 unk96;
|
||||
s32 unk100;
|
||||
u32 allocMem; // 104
|
||||
// make sure the size is 128
|
||||
u8 unk[20];
|
||||
} SceAudiocodecCodec;
|
||||
|
||||
void Register_sceAudiocodec();
|
@ -31,10 +31,20 @@ u32 sceP3daBridgeExit()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int getScaleValue(u32 channelsNum) {
|
||||
int val = 0;
|
||||
while (channelsNum > 1) {
|
||||
channelsNum >>= 1;
|
||||
val++;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 sceP3daBridgeCore(u32 p3daCoreAddr, u32 channelsNum, u32 samplesNum, u32 inputAddr, u32 outputAddr)
|
||||
{
|
||||
INFO_LOG(HLE, "sceP3daBridgeCore(%08x, %08x, %08x, %08x, %08x)", p3daCoreAddr, channelsNum, samplesNum, inputAddr, outputAddr);
|
||||
if (Memory::IsValidAddress(inputAddr) && Memory::IsValidAddress(outputAddr)) {
|
||||
int scaleval = getScaleValue(channelsNum);
|
||||
s16* outbuf = (s16*)Memory::GetPointer(outputAddr);
|
||||
memset(outbuf, 0, samplesNum * sizeof(s16) * 2);
|
||||
for (u32 k = 0; k < channelsNum; k++) {
|
||||
@ -43,8 +53,9 @@ u32 sceP3daBridgeCore(u32 p3daCoreAddr, u32 channelsNum, u32 samplesNum, u32 inp
|
||||
if (!inbuf)
|
||||
continue;
|
||||
for (u32 i = 0; i < samplesNum; i++) {
|
||||
outbuf[i*2] += inbuf[i];
|
||||
outbuf[i*2 + 1] += inbuf[i];
|
||||
s16 sample = inbuf[i] >> scaleval;
|
||||
outbuf[i*2] += sample;
|
||||
outbuf[i*2 + 1] += sample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -432,8 +432,14 @@ u32 sceSasSetSteepWave(u32 sasCore, int voice, int unknown) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 __sceSasSetVoiceATRAC3(u32 core, int voice, int atrac3Context) {
|
||||
ERROR_LOG_REPORT(HLE, "UNIMPL __sceSasSetVoiceATRAC3(%08x, %i, %i)", core, voice, atrac3Context);
|
||||
u32 __sceSasSetVoiceATRAC3(u32 core, int voiceNum, u32 atrac3Context) {
|
||||
INFO_LOG_REPORT(HLE, "__sceSasSetVoiceATRAC3(%08x, %i, %08x)", core, voiceNum, atrac3Context);
|
||||
SasVoice &v = sas->voices[voiceNum];
|
||||
u32 prevPcmAddr = v.pcmAddr;
|
||||
v.type = VOICETYPE_ATRAC3;
|
||||
v.loop = false;
|
||||
v.playing = true;
|
||||
v.atrac3.setContext(atrac3Context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -478,7 +484,7 @@ const HLEFunction sceSasCore[] =
|
||||
{0xe855bf76, WrapU_UU<sceSasSetOutputMode>, "__sceSasSetOutputmode"},
|
||||
{0x07f58c24, WrapU_UU<sceSasGetAllEnvelopeHeights>, "__sceSasGetAllEnvelopeHeights"},
|
||||
{0xE1CD9561, WrapU_UIUII<sceSasSetVoicePCM>, "__sceSasSetVoicePCM"},
|
||||
{0x4AA9EAD6, WrapU_UII<__sceSasSetVoiceATRAC3>,"__sceSasSetVoiceATRAC3"},
|
||||
{0x4AA9EAD6, WrapU_UIU<__sceSasSetVoiceATRAC3>,"__sceSasSetVoiceATRAC3"},
|
||||
{0x7497EA85, WrapU_UIUI<__sceSasConcatenateATRAC3>,"__sceSasConcatenateATRAC3"},
|
||||
{0xF6107F00, WrapU_UI<__sceSasUnsetATRAC3>,"__sceSasUnsetATRAC3"},
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "../Globals.h"
|
||||
#include "../MemMap.h"
|
||||
#include "Core/HLE/sceAtrac.h"
|
||||
#include "SasAudio.h"
|
||||
|
||||
// #define AUDIO_TO_FILE
|
||||
@ -152,6 +153,42 @@ void VagDecoder::DoState(PointerWrap &p)
|
||||
p.Do(end_);
|
||||
}
|
||||
|
||||
int SasAtrac3::setContext(u32 context) {
|
||||
contextAddr = context;
|
||||
atracID = _AtracGetIDByContext(context);
|
||||
if (!sampleQueue)
|
||||
sampleQueue = new Atrac3plus_Decoder::BufferQueue;
|
||||
sampleQueue->clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SasAtrac3::getNextSamples(s16* outbuf, int wantedSamples) {
|
||||
if (atracID < 0)
|
||||
return -1;
|
||||
u32 finish = 0;
|
||||
int wantedbytes = wantedSamples * sizeof(s16);
|
||||
while (!finish && sampleQueue->getQueueSize() < wantedbytes) {
|
||||
u32 numSamples = 0;
|
||||
int remains = 0;
|
||||
static s16 buf[0x800];
|
||||
_AtracDecodeData(atracID, (u8*)buf, &numSamples, &finish, &remains);
|
||||
if (numSamples > 0)
|
||||
sampleQueue->push((u8*)buf, numSamples * sizeof(s16));
|
||||
else
|
||||
finish = 1;
|
||||
}
|
||||
sampleQueue->pop_front((u8*)outbuf, wantedbytes);
|
||||
return finish;
|
||||
}
|
||||
|
||||
void SasAtrac3::DoState(PointerWrap &p) {
|
||||
p.Do(contextAddr);
|
||||
p.Do(atracID);
|
||||
if (p.mode == p.MODE_READ && atracID >= 0 && !sampleQueue) {
|
||||
sampleQueue = new Atrac3plus_Decoder::BufferQueue;
|
||||
}
|
||||
}
|
||||
|
||||
// http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java
|
||||
|
||||
int simpleRate(int n) {
|
||||
@ -340,6 +377,16 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VOICETYPE_ATRAC3:
|
||||
{
|
||||
int ret = voice.atrac3.getNextSamples(resampleBuffer + 2, numSamples);
|
||||
if (ret) {
|
||||
// Hit atrac3 voice end
|
||||
voice.playing = false;
|
||||
voice.on = false; // ??
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
memset(resampleBuffer + 2, 0, numSamples * sizeof(s16));
|
||||
@ -529,6 +576,7 @@ void SasVoice::DoState(PointerWrap &p)
|
||||
|
||||
envelope.DoState(p);
|
||||
vag.DoState(p);
|
||||
atrac3.DoState(p);
|
||||
}
|
||||
|
||||
// This is horribly stolen from JPCSP.
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "../Globals.h"
|
||||
#include "ChunkFile.h"
|
||||
|
||||
#include "Core/HW/atrac3plus.h"
|
||||
|
||||
enum {
|
||||
PSP_SAS_VOICES_MAX = 32,
|
||||
|
||||
@ -106,6 +108,19 @@ private:
|
||||
bool end_;
|
||||
};
|
||||
|
||||
class SasAtrac3 {
|
||||
public:
|
||||
SasAtrac3() : contextAddr(0), atracID(-1), sampleQueue(0){}
|
||||
~SasAtrac3() { if (sampleQueue) delete sampleQueue; }
|
||||
int setContext(u32 context);
|
||||
int getNextSamples(s16* outbuf, int wantedSamples);
|
||||
void DoState(PointerWrap &p);
|
||||
private:
|
||||
u32 contextAddr;
|
||||
int atracID;
|
||||
Atrac3plus_Decoder::BufferQueue *sampleQueue;
|
||||
};
|
||||
|
||||
// Max height: 0x40000000 I think
|
||||
class ADSREnvelope
|
||||
{
|
||||
@ -218,6 +233,7 @@ struct SasVoice
|
||||
ADSREnvelope envelope;
|
||||
|
||||
VagDecoder vag;
|
||||
SasAtrac3 atrac3;
|
||||
};
|
||||
|
||||
class SasInstance
|
||||
|
@ -85,6 +85,7 @@ Building for Linux/BSD/Meego Harmattan/Pandora/etc
|
||||
--------------------------
|
||||
|
||||
Qt (recommended)
|
||||
|
||||
A Qt-based frontend is available in the Qt/ dir.
|
||||
Open PPSSPPQt.pro with [Qt Creator 2.6+][qt-creator].
|
||||
Install libsdl1.2 if you want to use USB Gamepad.
|
||||
@ -92,9 +93,12 @@ If the build has an error about finding mobility or multimedia:
|
||||
- Install the package "qtmobility-dev"
|
||||
|
||||
SDL
|
||||
|
||||
Alternatively, install the libsdl1.2 (SDL 1.2) development headers. This is called `libsdl1.2-dev` on Debian/Ubuntu, `SDL-devel` on Fedora/RHEL,
|
||||
`sdl12` on BSD ports.
|
||||
|
||||
You will need a recent version of ffmpeg (1.1 or greater, which means libav 9.1 or greater probably) or development packets (for distributions with separate packets) for libavformat, libavcodec, libswresample and libswscale (still version 9.1 or greater).
|
||||
|
||||
Currently the user interface is identical to Android's, operated
|
||||
with the mouse.
|
||||
|
||||
|
@ -288,6 +288,7 @@ void GameInfoCache::FlushBGs() {
|
||||
delete iter->second->pic1Texture;
|
||||
iter->second->pic1Texture = 0;
|
||||
}
|
||||
iter->second->wantBG = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
class GameInfo {
|
||||
public:
|
||||
GameInfo() : fileType(FILETYPE_UNKNOWN), iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), paramSFOLoaded(false) {}
|
||||
GameInfo() : fileType(FILETYPE_UNKNOWN), iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantBG(false), paramSFOLoaded(false) {}
|
||||
|
||||
bool DeleteGame(); // Better be sure what you're doing when calling this.
|
||||
bool DeleteAllSaveData();
|
||||
@ -110,4 +110,4 @@ private:
|
||||
};
|
||||
|
||||
// This one can be global, no good reason not to.
|
||||
extern GameInfoCache g_gameInfoCache;
|
||||
extern GameInfoCache g_gameInfoCache;
|
||||
|
@ -216,6 +216,7 @@ LOCAL_SRC_FILES := \
|
||||
$(SRC)/Core/HLE/sceAtrac.cpp \
|
||||
$(SRC)/Core/HLE/__sceAudio.cpp \
|
||||
$(SRC)/Core/HLE/sceAudio.cpp \
|
||||
$(SRC)/Core/HLE/sceAudioCodec.cpp \
|
||||
$(SRC)/Core/HLE/sceChnnlsv.cpp \
|
||||
$(SRC)/Core/HLE/sceCtrl.cpp \
|
||||
$(SRC)/Core/HLE/sceDeflt.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user