diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 6a5f9720be..8d0b52415d 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -25,6 +25,10 @@ #include "base/logging.h" #include "base/timeutil.h" +#ifndef _XBOX +#include "gfx_es2/gl_state.h" +#endif + #include "Common/Thread.h" #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" @@ -179,7 +183,7 @@ void __DisplayInit() { } void __DisplayDoState(PointerWrap &p) { - auto s = p.Section("sceDisplay", 1); + auto s = p.Section("sceDisplay", 1, 2); if (!s) return; @@ -205,10 +209,17 @@ void __DisplayDoState(PointerWrap &p) { p.Do(leaveVblankEvent); CoreTiming::RestoreRegisterEvent(leaveVblankEvent, "LeaveVBlank", &hleLeaveVblank); p.Do(afterFlipEvent); - CoreTiming::RestoreRegisterEvent(afterFlipEvent, "AfterFlipEVent", &hleAfterFlip); + CoreTiming::RestoreRegisterEvent(afterFlipEvent, "AfterFlip", &hleAfterFlip); p.Do(gstate); p.Do(gstate_c); +#ifndef _XBOX + if (s < 2) { + // This shouldn't have been savestated anyway, but it was. + // It's unlikely to overlap with the first value in gpuStats. + p.ExpectVoid(&gl_extensions.gpuVendor, sizeof(gl_extensions.gpuVendor)); + } +#endif p.Do(gpuStats); gpu->DoState(p); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index d87480adaa..e242f3e72d 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -58,6 +58,7 @@ #include "sceKernelEventFlag.h" #include "sceKernelVTimer.h" #include "sceKernelTime.h" +#include "sceMp3.h" #include "sceMpeg.h" #include "sceNet.h" #include "sceNetAdhoc.h" @@ -157,6 +158,7 @@ void __KernelShutdown() __NetAdhocShutdown(); __FontShutdown(); + __Mp3Shutdown(); __MpegShutdown(); __PsmfShutdown(); __PPGeShutdown(); @@ -231,6 +233,7 @@ void __KernelDoState(PointerWrap &p) __ImposeDoState(p); __IoDoState(p); __JpegDoState(p); + __Mp3DoState(p); __MpegDoState(p); __NetDoState(p); __NetAdhocDoState(p); diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index 87eba22da1..5c9e6ab696 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -22,7 +22,6 @@ #include "Core/HLE/sceMp3.h" #include "Core/HW/MediaEngine.h" #include "Core/Reporting.h" -#include "Core/HW/MediaEngine.h" #ifdef USE_FFMPEG #ifndef PRId64 @@ -40,11 +39,37 @@ extern "C" { static const int MP3_BITRATES[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; +struct Mp3Context; +int __Mp3InitContext(Mp3Context *ctx); + struct Mp3Context { + Mp3Context() +#ifdef USE_FFMPEG + : avformat_context(NULL), avio_context(NULL), resampler_context(NULL) { +#else + { +#endif + } + + ~Mp3Context() { +#ifdef USE_FFMPEG + if (avio_context != NULL) { + av_free(avio_context->buffer); + av_free(avio_context); + } + if (avformat_context != NULL) { + avformat_free_context(avformat_context); + } + if (resampler_context != NULL) { + swr_free(&resampler_context); + } +#endif + } + void DoState(PointerWrap &p) { - auto s = p.Section("Mp3Context", 1, 2); - if (!s) - return; + auto s = p.Section("Mp3Context", 1); + if (!s) + return; p.Do(mp3StreamStart); p.Do(mp3StreamEnd); @@ -52,18 +77,20 @@ struct Mp3Context { p.Do(mp3BufSize); p.Do(mp3PcmBuf); p.Do(mp3PcmBufSize); + p.Do(readPosition); + p.Do(bufferRead); + p.Do(bufferWrite); + p.Do(bufferAvailable); p.Do(mp3DecodedBytes); - if (s >= 2) - p.Do(mp3SumDecodedSamples); - else - mp3SumDecodedSamples = 0; p.Do(mp3LoopNum); p.Do(mp3MaxSamples); - p.Do(mp3Bitrate); + p.Do(mp3SumDecodedSamples); p.Do(mp3Channels); + p.Do(mp3Bitrate); p.Do(mp3SamplingRate); p.Do(mp3Version); - p.DoClass(mediaengine); + + __Mp3InitContext(this); } int mp3StreamStart; @@ -83,7 +110,6 @@ struct Mp3Context { int mp3LoopNum; int mp3MaxSamples; int mp3SumDecodedSamples; - MediaEngine *mediaengine; int mp3Channels; int mp3Bitrate; @@ -99,19 +125,28 @@ struct Mp3Context { }; static std::map mp3Map; -static u32 lastMp3Handle = 0; Mp3Context *getMp3Ctx(u32 mp3) { - if (mp3Map.find(mp3) == mp3Map.end()) { - ERROR_LOG(ME, "Bad mp3 handle %08x - using last one (%08x) instead", mp3, lastMp3Handle); - mp3 = lastMp3Handle; - } - if (mp3Map.find(mp3) == mp3Map.end()) return NULL; return mp3Map[mp3]; } +void __Mp3Shutdown() { + for (auto it = mp3Map.begin(), end = mp3Map.end(); it != end; ++it) { + delete it->second; + } + mp3Map.clear(); +} + +void __Mp3DoState(PointerWrap &p) { + auto s = p.Section("sceMp3", 0, 1); + if (!s) + return; + + p.Do(mp3Map); +} + /* MP3 */ int sceMp3Decode(u32 mp3, u32 outPcmPtr) { DEBUG_LOG(ME, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr); @@ -236,7 +271,7 @@ int sceMp3CheckStreamDataNeeded(u32 mp3) { return ctx->bufferAvailable != ctx->mp3BufSize && ctx->readPosition < ctx->mp3StreamEnd; } -int readFunc(void *opaque, uint8_t *buf, int buf_size) { +static int readFunc(void *opaque, uint8_t *buf, int buf_size) { Mp3Context *ctx = static_cast(opaque); int res = 0; @@ -300,11 +335,6 @@ u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { ctx->mp3Bitrate = 128; ctx->mp3SamplingRate = 44100; -#ifdef USE_FFMPEG - ctx->avformat_context = NULL; - ctx->avio_context = NULL; -#endif - mp3Map[mp3Addr] = ctx; return mp3Addr; } @@ -321,28 +351,10 @@ int sceMp3TermResource() { return 0; } -int sceMp3Init(u32 mp3) { - DEBUG_LOG(ME, "sceMp3Init(%08x)", mp3); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) { - ERROR_LOG(ME, "%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); - - ctx->mp3Version = ((header >> 19) & 0x3); - +int __Mp3InitContext(Mp3Context *ctx) { #ifdef USE_FFMPEG InitFFmpeg(); - - u8* avio_buffer = static_cast(av_malloc(ctx->mp3BufSize)); + u8 *avio_buffer = static_cast(av_malloc(ctx->mp3BufSize)); ctx->avio_context = avio_alloc_context(avio_buffer, ctx->mp3BufSize, 0, ctx, readFunc, NULL, NULL); ctx->avformat_context = avformat_alloc_context(); ctx->avformat_context->pb = ctx->avio_context; @@ -384,12 +396,6 @@ int sceMp3Init(u32 mp3) { ctx->decoder_context->sample_rate, 0, NULL); - // Let's just grab this info from FFMPEG, it seems more reliable than the code above. - - ctx->mp3SamplingRate = ctx->decoder_context->sample_rate; - ctx->mp3Channels = ctx->decoder_context->channels; - ctx->mp3Bitrate = ctx->decoder_context->bit_rate / 1000; - if (!ctx->resampler_context) { ERROR_LOG(ME, "Could not allocate resampler context %d", ret); return -1; @@ -400,6 +406,39 @@ int sceMp3Init(u32 mp3) { return -1; } + return 0; +#endif +} + +int sceMp3Init(u32 mp3) { + DEBUG_LOG(ME, "sceMp3Init(%08x)", mp3); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(ME, "%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); + + ctx->mp3Version = ((header >> 19) & 0x3); + +#ifdef USE_FFMPEG + int ret = __Mp3InitContext(ctx); + if (ret != 0) + return ret; + + // Let's just grab this info from FFMPEG, it seems more reliable than the code above. + + ctx->mp3SamplingRate = ctx->decoder_context->sample_rate; + ctx->mp3Channels = ctx->decoder_context->channels; + ctx->mp3Bitrate = ctx->decoder_context->bit_rate / 1000; + av_dump_format(ctx->avformat_context, 0, "mp3", 0); #endif @@ -549,10 +588,6 @@ int sceMp3ReleaseMp3Handle(u32 mp3) { return -1; } -#ifdef USE_FFMPEG - av_free(ctx->avio_context->buffer); - av_free(ctx->avio_context); -#endif mp3Map.erase(mp3Map.find(mp3)); delete ctx; diff --git a/Core/HLE/sceMp3.h b/Core/HLE/sceMp3.h index f855286ecd..f4ca0b0b5e 100644 --- a/Core/HLE/sceMp3.h +++ b/Core/HLE/sceMp3.h @@ -19,4 +19,9 @@ #include "HLE.h" -void Register_sceMp3(); \ No newline at end of file +class PointerWrap; + +void Register_sceMp3(); + +void __Mp3Shutdown(); +void __Mp3DoState(PointerWrap &p); \ No newline at end of file