Merge branch 'master' of github.com:hrydgard/ppsspp

Conflicts:
	UI/GameInfoCache.h
This commit is contained in:
Henrik Rydgard 2013-06-08 23:01:49 +02:00
commit 533541615f
17 changed files with 393 additions and 58 deletions

View File

@ -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

View File

@ -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

View File

@ -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" />

View File

@ -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" />

View File

@ -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++)
{

View File

@ -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};

View File

@ -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);

View 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
View 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();

View File

@ -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;
}
}
}

View File

@ -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"},
};

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -288,6 +288,7 @@ void GameInfoCache::FlushBGs() {
delete iter->second->pic1Texture;
iter->second->pic1Texture = 0;
}
iter->second->wantBG = false;
}
}

View File

@ -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;

View File

@ -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 \