diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c2800ec37..fa5e2b0fac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,11 @@ else() # Assume x86 set(X86 ON) endif() -if(ANDROID OR BLACKBERRY OR IOS OR PANDORA OR MAEMO) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(MACOSX ON) +endif() + +if(ANDROID OR BLACKBERRY OR IOS OR PANDORA OR MAEMO OR MACOSX) set(HEADLESS OFF) elseif(NOT DEFINED HEADLESS) set(HEADLESS ON) @@ -472,6 +476,12 @@ elseif(BLACKBERRY) set(nativeExtraLibs ${nativeExtraLibs} iconv libavformat.a libavcodec.a libswresample.a libavutil.a libswscale.a) set(TargetBin PPSSPPBlackberry) elseif(SDL_FOUND) + if(MACOSX) + include_directories(ffmpeg/macosx/x86_64/include) + link_directories(ffmpeg/macosx/x86_64/lib) + set(nativeExtraLibs ${nativeExtraLibs} libavformat.a libavcodec.a libswresample.a libavutil.a libswscale.a) + endif() + set(TargetBin PPSSPPSDL) # Require SDL include_directories(${SDL_INCLUDE_DIR}) set(nativeExtra ${nativeExtra} native/base/PCMain.cpp) diff --git a/Common/ConsoleListener.cpp b/Common/ConsoleListener.cpp index 0dfcf3914f..e5d3ef9c4c 100644 --- a/Common/ConsoleListener.cpp +++ b/Common/ConsoleListener.cpp @@ -101,7 +101,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title if (hTriggerEvent != NULL && hThread == NULL) { logPending = new char[LOG_PENDING_MAX]; - hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ConsoleListener::RunThread, this, 0, NULL); + hThread = (HANDLE)_beginthreadex(NULL, 0, &ConsoleListener::RunThread, this, 0, NULL); } #endif } @@ -246,9 +246,9 @@ COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth) return Ret; } -DWORD WINAPI ConsoleListener::RunThread(LPVOID lpParam) +unsigned int WINAPI ConsoleListener::RunThread(void *lpParam) { - ConsoleListener *consoleLog = (ConsoleListener *) lpParam; + ConsoleListener *consoleLog = (ConsoleListener *)lpParam; consoleLog->LogWriterThread(); return 0; } diff --git a/Common/ConsoleListener.h b/Common/ConsoleListener.h index 42547c0a00..1eff61a358 100644 --- a/Common/ConsoleListener.h +++ b/Common/ConsoleListener.h @@ -50,7 +50,7 @@ private: HWND GetHwnd(void); HANDLE hConsole; - static DWORD WINAPI RunThread(LPVOID lpParam); + static unsigned int WINAPI RunThread(void *lpParam); void LogWriterThread(); void SendToThread(LogTypes::LOG_LEVELS Level, const char *Text); void WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Text, size_t Len); diff --git a/Core/Config.cpp b/Core/Config.cpp index ab159f20ae..f9c793b871 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -119,11 +119,7 @@ void Config::Load(const char *iniFileName) #endif graphics->Get("StretchToDisplay", &bStretchToDisplay, false); graphics->Get("TrueColor", &bTrueColor, true); -#ifdef USING_GLES2 graphics->Get("MipMap", &bMipMap, true); -#else - graphics->Get("MipMap", &bMipMap, false); -#endif graphics->Get("TexScalingLevel", &iTexScalingLevel, 1); graphics->Get("TexScalingType", &iTexScalingType, 0); graphics->Get("TexDeposterize", &bTexDeposterize, false); diff --git a/Core/Core.cpp b/Core/Core.cpp index 951a0578fd..d1170cce73 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -70,6 +70,11 @@ bool Core_IsStepping() return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN; } +bool Core_IsActive() +{ + return coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME || coreStatePending; +} + bool Core_IsInactive() { return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending; @@ -77,7 +82,7 @@ bool Core_IsInactive() void Core_WaitInactive() { - while (!Core_IsInactive()) + while (Core_IsActive()) m_hInactiveEvent.wait(m_hInactiveMutex); } diff --git a/Core/Core.h b/Core/Core.h index 2994ca55fe..b26103b740 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -33,6 +33,7 @@ void Core_Halt(const char *msg); bool Core_IsStepping(); +bool Core_IsActive(); bool Core_IsInactive(); void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index ddb5687473..ce13c922d1 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -23,7 +23,7 @@ #include "ChunkFile.h" #include "i18n/i18n.h" -const float FONT_SCALE = 0.55f; +const float FONT_SCALE = 0.50f; PSPMsgDialog::PSPMsgDialog() : PSPDialog() @@ -132,8 +132,9 @@ int PSPMsgDialog::Init(unsigned int paramAddr) void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo) { - const float WRAP_WIDTH = 350.0f; - float y = 136.0f, h; + const float WRAP_WIDTH = 450.0f; + float y = 136.0f; + float h; int n; PPGeMeasureText(0, &h, &n, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH); float h2 = h * (float)n / 2.0f; @@ -173,8 +174,8 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo) } PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); float sy = 122.0f - h2, ey = 150.0f + h2; - PPGeDrawRect(60.0f, sy, 420.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); - PPGeDrawRect(60.0f, ey, 420.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawRect(30.0f, sy, 450.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawRect(30.0f, ey, 450.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); } int PSPMsgDialog::Update() diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index b217e8394e..96c36aa9ad 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -913,7 +913,9 @@ u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFirstBuf, #ifdef USE_FFMPEG int _AtracReadbuffer(void *opaque, uint8_t *buf, int buf_size) { - Atrac *atrac = (Atrac*)opaque; + Atrac *atrac = (Atrac *)opaque; + if (atrac->decodePos > atrac->first.filesize) + return -1; int size = std::min((int)atrac->atracBufSize, buf_size); size = std::max(std::min(((int)atrac->first.size - (int)atrac->decodePos), size), 0); if (size > 0) @@ -925,6 +927,9 @@ int _AtracReadbuffer(void *opaque, uint8_t *buf, int buf_size) int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence) { Atrac *atrac = (Atrac*)opaque; + if (offset > atrac->first.filesize) + return -1; + switch (whence) { case SEEK_SET: atrac->decodePos = (u32)offset; @@ -935,8 +940,12 @@ int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence) case SEEK_END: atrac->decodePos = atrac->first.filesize - (u32)offset; break; +#ifdef USE_FFMPEG + case AVSEEK_SIZE: + return atrac->first.filesize; +#endif } - return offset; + return atrac->decodePos; } #endif // USE_FFMPEG diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 2859a9baaf..942ce0bd6f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2136,27 +2136,31 @@ int sceKernelRotateThreadReadyQueue(int priority) return 0; } -int sceKernelDeleteThread(int threadHandle) +int sceKernelDeleteThread(int threadID) { - if (threadHandle != currentThread) + if (threadID == 0 || threadID == currentThread) { - DEBUG_LOG(HLE,"sceKernelDeleteThread(%i)",threadHandle); + ERROR_LOG(HLE, "sceKernelDeleteThread(%i): cannot delete current thread", threadID); + return SCE_KERNEL_ERROR_NOT_DORMANT; + } - u32 error; - Thread *t = kernelObjects.Get(threadHandle, error); - if (t) + u32 error; + Thread *t = kernelObjects.Get(threadID, error); + if (t) + { + if (!t->isStopped()) { - // TODO: Should this reschedule ever? Probably no? - return __KernelDeleteThread(threadHandle, SCE_KERNEL_ERROR_THREAD_TERMINATED, "thread deleted", true); + ERROR_LOG(HLE, "sceKernelDeleteThread(%i): thread not dormant", threadID); + return SCE_KERNEL_ERROR_NOT_DORMANT; } - // TODO: Error when doesn't exist? - return 0; + DEBUG_LOG(HLE, "sceKernelDeleteThread(%i)", threadID); + return __KernelDeleteThread(threadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "thread deleted", true); } else { - ERROR_LOG_REPORT(HLE, "Thread \"%s\" tries to delete itself! :(", __GetCurrentThread() ? __GetCurrentThread()->GetName() : "NULL"); - return -1; + ERROR_LOG(HLE, "sceKernelDeleteThread(%i): thread doesn't exist", threadID); + return error; } } @@ -2173,9 +2177,7 @@ int sceKernelTerminateDeleteThread(int threadID) if (t) { INFO_LOG(HLE, "sceKernelTerminateDeleteThread(%i)", threadID); - //TODO: should we really reschedule here? - error = __KernelDeleteThread(threadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "thread terminated with delete", false); - hleReSchedule("thread terminated with delete"); + error = __KernelDeleteThread(threadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "thread terminated with delete", true); return error; } diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index df1a7ee6bf..c7c1ab7448 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -246,13 +246,11 @@ Psmf::Psmf(u32 data) { u32 currentStreamAddr = data + 0x82 + i * 16; int streamId = Memory::Read_U8(currentStreamAddr); if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) { - stream = new PsmfStream(PSMF_AVC_STREAM, 0); + stream = new PsmfStream(PSMF_AVC_STREAM, ++currentVideoStreamNum); stream->readMPEGVideoStreamParams(currentStreamAddr, this); - currentVideoStreamNum++; } else if ((streamId & PSMF_AUDIO_STREAM_ID) == PSMF_AUDIO_STREAM_ID) { - stream = new PsmfStream(PSMF_ATRAC_STREAM, 1); + stream = new PsmfStream(PSMF_ATRAC_STREAM, ++currentAudioStreamNum); stream->readPrivateAudioStreamParams(currentStreamAddr, this); - currentAudioStreamNum++; } if (stream) { currentStreamNum++; @@ -436,7 +434,7 @@ u32 scePsmfGetNumberOfStreams(u32 psmfStruct) { Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetNumberOfStreams - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetNumberOfStreams(%08x): invalid psmf", psmfStruct); return ERROR_PSMF_NOT_FOUND; } DEBUG_LOG(HLE, "scePsmfGetNumberOfStreams(%08x)", psmfStruct); @@ -447,18 +445,24 @@ u32 scePsmfGetNumberOfSpecificStreams(u32 psmfStruct, u32 streamType) { Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetNumberOfSpecificStreams - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetNumberOfSpecificStreams(%08x, %08x): invalid psmf", psmfStruct, streamType); return ERROR_PSMF_NOT_FOUND; } - INFO_LOG(HLE, "scePsmfGetNumberOfSpecificStreams(%08x, %08x)", psmfStruct, streamType); - return 1; + WARN_LOG(HLE, "scePsmfGetNumberOfSpecificStreams(%08x, %08x)", psmfStruct, streamType); + int streamNum = 0; + int type = (streamType == PSMF_AUDIO_STREAM ? PSMF_ATRAC_STREAM : streamType); + for (int i = psmf->streamMap.size() - 1; i >= 0; i--) { + if (psmf->streamMap[i]->type == type) + streamNum++; + } + return streamNum; } u32 scePsmfSpecifyStreamWithStreamType(u32 psmfStruct, u32 streamType, u32 channel) { Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfSpecifyStreamWithStreamType - invalid psmf"); + ERROR_LOG(HLE, "scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i): invalid psmf", psmfStruct, streamType, channel); return ERROR_PSMF_NOT_FOUND; } ERROR_LOG(HLE, "UNIMPL scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i)", psmfStruct, streamType, channel); @@ -472,17 +476,17 @@ u32 scePsmfSpecifyStreamWithStreamTypeNumber(u32 psmfStruct, u32 streamType, u32 { Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfSpecifyStream - invalid psmf"); + ERROR_LOG(HLE, "scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x): invalid psmf", psmfStruct, streamType, typeNum); return ERROR_PSMF_NOT_FOUND; } - ERROR_LOG(HLE, "UNIMPL scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x)", psmfStruct, streamType, typeNum); + ERROR_LOG_REPORT(HLE, "UNIMPL scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x)", psmfStruct, streamType, typeNum); return 0; } u32 scePsmfSpecifyStream(u32 psmfStruct, int streamNum) { Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfSpecifyStream - invalid psmf"); + ERROR_LOG(HLE, "scePsmfSpecifyStream(%08x, %i): invalid psmf", psmfStruct, streamNum); return ERROR_PSMF_NOT_FOUND; } INFO_LOG(HLE, "scePsmfSpecifyStream(%08x, %i)", psmfStruct, streamNum); @@ -491,26 +495,26 @@ u32 scePsmfSpecifyStream(u32 psmfStruct, int streamNum) { } u32 scePsmfGetVideoInfo(u32 psmfStruct, u32 videoInfoAddr) { - INFO_LOG(HLE, "scePsmfGetVideoInfo(%08x, %08x)", psmfStruct, videoInfoAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetNumberOfSpecificStreams - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetVideoInfo(%08x, %08x): invalid psmf", psmfStruct, videoInfoAddr); return ERROR_PSMF_NOT_FOUND; } + INFO_LOG(HLE, "scePsmfGetVideoInfo(%08x, %08x)", psmfStruct, videoInfoAddr); if (Memory::IsValidAddress(videoInfoAddr)) { Memory::Write_U32(psmf->videoWidth, videoInfoAddr); - Memory::Write_U32(psmf->videoWidth, videoInfoAddr + 4); + Memory::Write_U32(psmf->videoHeight, videoInfoAddr + 4); } return 0; } u32 scePsmfGetAudioInfo(u32 psmfStruct, u32 audioInfoAddr) { - INFO_LOG(HLE, "scePsmfGetAudioInfo(%08x, %08x)", psmfStruct, audioInfoAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetNumberOfSpecificStreams - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetAudioInfo(%08x, %08x): invalid psmf", psmfStruct, audioInfoAddr); return ERROR_PSMF_NOT_FOUND; } + INFO_LOG(HLE, "scePsmfGetAudioInfo(%08x, %08x)", psmfStruct, audioInfoAddr); if (Memory::IsValidAddress(audioInfoAddr)) { Memory::Write_U32(psmf->audioChannels, audioInfoAddr); Memory::Write_U32(psmf->audioFrequency, audioInfoAddr + 4); @@ -519,12 +523,12 @@ u32 scePsmfGetAudioInfo(u32 psmfStruct, u32 audioInfoAddr) { } u32 scePsmfGetCurrentStreamType(u32 psmfStruct, u32 typeAddr, u32 channelAddr) { - INFO_LOG(HLE, "scePsmfGetCurrentStreamType(%08x, %08x, %08x)", psmfStruct, typeAddr, channelAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetCurrentStreamType - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetCurrentStreamType(%08x, %08x, %08x): invalid psmf", psmfStruct, typeAddr, channelAddr); return ERROR_PSMF_NOT_FOUND; } + INFO_LOG(HLE, "scePsmfGetCurrentStreamType(%08x, %08x, %08x)", psmfStruct, typeAddr, channelAddr); if (Memory::IsValidAddress(typeAddr)) { u32 type = 0, channel = 0; if (psmf->streamMap.find(psmf->currentStreamNum) != psmf->streamMap.end()) @@ -539,12 +543,12 @@ u32 scePsmfGetCurrentStreamType(u32 psmfStruct, u32 typeAddr, u32 channelAddr) { u32 scePsmfGetStreamSize(u32 psmfStruct, u32 sizeAddr) { - DEBUG_LOG(HLE, "scePsmfGetStreamSize(%08x, %08x)", psmfStruct, sizeAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetStreamSize - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetStreamSize(%08x, %08x): invalid psmf", psmfStruct, sizeAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetStreamSize(%08x, %08x)", psmfStruct, sizeAddr); if (Memory::IsValidAddress(sizeAddr)) { Memory::Write_U32(psmf->streamSize, sizeAddr); } @@ -553,7 +557,7 @@ u32 scePsmfGetStreamSize(u32 psmfStruct, u32 sizeAddr) u32 scePsmfQueryStreamOffset(u32 bufferAddr, u32 offsetAddr) { - ERROR_LOG(HLE, "UNIMPL scePsmfQueryStreamOffset(%08x, %08x)", bufferAddr, offsetAddr); + WARN_LOG(HLE, "scePsmfQueryStreamOffset(%08x, %08x)", bufferAddr, offsetAddr); if (Memory::IsValidAddress(offsetAddr)) { Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_OFFSET_OFFSET)), offsetAddr); } @@ -562,7 +566,7 @@ u32 scePsmfQueryStreamOffset(u32 bufferAddr, u32 offsetAddr) u32 scePsmfQueryStreamSize(u32 bufferAddr, u32 sizeAddr) { - ERROR_LOG(HLE, "UNIMPL scePsmfQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr); + WARN_LOG(HLE, "scePsmfQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr); if (Memory::IsValidAddress(sizeAddr)) { Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_SIZE_OFFSET)), sizeAddr); } @@ -571,12 +575,12 @@ u32 scePsmfQueryStreamSize(u32 bufferAddr, u32 sizeAddr) u32 scePsmfGetHeaderSize(u32 psmfStruct, u32 sizeAddr) { - DEBUG_LOG(HLE, "scePsmfGetHeaderSize(%08x, %08x)", psmfStruct, sizeAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetHeaderSize - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetHeaderSize(%08x, %08x): invalid psmf", psmfStruct, sizeAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetHeaderSize(%08x, %08x)", psmfStruct, sizeAddr); if (Memory::IsValidAddress(sizeAddr)) { Memory::Write_U32(psmf->headerSize, sizeAddr); } @@ -585,50 +589,50 @@ u32 scePsmfGetHeaderSize(u32 psmfStruct, u32 sizeAddr) u32 scePsmfGetPsmfVersion(u32 psmfStruct) { - DEBUG_LOG(HLE, "scePsmfGetPsmfVersion(%08x)", psmfStruct); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetHeaderSize - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetHeaderSize(%08x): invalid psmf", psmfStruct); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetPsmfVersion(%08x)", psmfStruct); return psmf->version; } u32 scePsmfVerifyPsmf(u32 psmfAddr) { - DEBUG_LOG(HLE, "scePsmfVerifyPsmf(%08x)", psmfAddr); int magic = Memory::Read_U32(psmfAddr); if (magic != PSMF_MAGIC) { - ERROR_LOG(HLE, "scePsmfVerifyPsmf - bad magic"); + ERROR_LOG(HLE, "scePsmfVerifyPsmf(%08x): bad magic %08x", psmfAddr, magic); return ERROR_PSMF_NOT_FOUND; } int version = Memory::Read_U32(psmfAddr + PSMF_STREAM_VERSION_OFFSET); if (version < 0) { - ERROR_LOG(HLE, "scePsmfVerifyPsmf - bad version"); + ERROR_LOG(HLE, "scePsmfVerifyPsmf(%08x): bad version %08x", psmfAddr, version); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfVerifyPsmf(%08x)", psmfAddr); return 0; } u32 scePsmfGetNumberOfEPentries(u32 psmfStruct) { - DEBUG_LOG(HLE, "scePsmfGetNumberOfEPentries(%08x)", psmfStruct); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetNumberOfEPentries - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetNumberOfEPentries(%08x): invalid psmf", psmfStruct); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetNumberOfEPentries(%08x)", psmfStruct); return psmf->EPMapEntriesNum; } u32 scePsmfGetPresentationStartTime(u32 psmfStruct, u32 startTimeAddr) { - DEBUG_LOG(HLE, "scePsmfGetPresentationStartTime(%08x, %08x)", psmfStruct, startTimeAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetPresentationStartTime - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetPresentationStartTime(%08x, %08x): invalid psmf", psmfStruct, startTimeAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetPresentationStartTime(%08x, %08x)", psmfStruct, startTimeAddr); if (Memory::IsValidAddress(startTimeAddr)) { Memory::Write_U32(psmf->presentationStartTime, startTimeAddr); } @@ -637,12 +641,12 @@ u32 scePsmfGetPresentationStartTime(u32 psmfStruct, u32 startTimeAddr) u32 scePsmfGetPresentationEndTime(u32 psmfStruct, u32 endTimeAddr) { - DEBUG_LOG(HLE, "scePsmfGetPresentationEndTime(%08x, %08x)", psmfStruct, endTimeAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetPresentationEndTime - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetPresentationEndTime(%08x, %08x): invalid psmf", psmfStruct, endTimeAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetPresentationEndTime(%08x, %08x)", psmfStruct, endTimeAddr); if (Memory::IsValidAddress(endTimeAddr)) { Memory::Write_U32(psmf->presentationEndTime, endTimeAddr); } @@ -651,24 +655,24 @@ u32 scePsmfGetPresentationEndTime(u32 psmfStruct, u32 endTimeAddr) u32 scePsmfGetCurrentStreamNumber(u32 psmfStruct) { - DEBUG_LOG(HLE, "scePsmfGetCurrentStreamNumber(%08x)", psmfStruct); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetCurrentStreamNumber - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetCurrentStreamNumber(%08x): invalid psmf", psmfStruct); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetCurrentStreamNumber(%08x)", psmfStruct); return psmf->currentStreamNum; } u32 scePsmfGetEPWithId(u32 psmfStruct, int id, u32 outAddr) { - DEBUG_LOG(HLE, "scePsmfGetEPWithId(%08x, %i, %08x)", psmfStruct, id, outAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetEPWithId - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetEPWithId(%08x, %i, %08x): invalid psmf", psmfStruct, id, outAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetEPWithId(%08x, %i, %08x)", psmfStruct, id, outAddr); if (Memory::IsValidAddress(outAddr)) { Memory::Write_U32(psmf->psmfEntry.EPPts, outAddr); Memory::Write_U32(psmf->psmfEntry.EPOffset, outAddr + 4); @@ -680,12 +684,12 @@ u32 scePsmfGetEPWithId(u32 psmfStruct, int id, u32 outAddr) u32 scePsmfGetEPWithTimestamp(u32 psmfStruct, u32 ts, u32 entryAddr) { - DEBUG_LOG(HLE, "scePsmfGetEPWithTimestamp(%08x, %i, %08x)", psmfStruct, ts, entryAddr); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetEPWithTimestamp - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetEPWithTimestamp(%08x, %i, %08x): invalid psmf", psmfStruct, ts, entryAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetEPWithTimestamp(%08x, %i, %08x)", psmfStruct, ts, entryAddr); if (ts < psmf->presentationStartTime) { return ERROR_PSMF_INVALID_TIMESTAMP; } @@ -700,12 +704,12 @@ u32 scePsmfGetEPWithTimestamp(u32 psmfStruct, u32 ts, u32 entryAddr) u32 scePsmfGetEPidWithTimestamp(u32 psmfStruct, u32 ts) { - DEBUG_LOG(HLE, "scePsmfGetEPidWithTimestamp(%08x, %i)", psmfStruct, ts); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { - ERROR_LOG(HLE, "scePsmfGetEPidWithTimestamp - invalid psmf"); + ERROR_LOG(HLE, "scePsmfGetEPidWithTimestamp(%08x, %i): invalid psmf", psmfStruct, ts); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetEPidWithTimestamp(%08x, %i)", psmfStruct, ts); if (ts < psmf->presentationStartTime) { return ERROR_PSMF_INVALID_TIMESTAMP; } @@ -715,7 +719,7 @@ u32 scePsmfGetEPidWithTimestamp(u32 psmfStruct, u32 ts) int scePsmfPlayerCreate(u32 psmfPlayer, u32 psmfPlayerDataAddr) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerCreate(%08x, %08x)", psmfPlayer, psmfPlayerDataAddr); + WARN_LOG(HLE, "scePsmfPlayerCreate(%08x, %08x)", psmfPlayer, psmfPlayerDataAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { // TODO: This is the wrong data. PsmfPlayer needs a new interface. @@ -736,7 +740,7 @@ int scePsmfPlayerCreate(u32 psmfPlayer, u32 psmfPlayerDataAddr) int scePsmfPlayerStop(u32 psmfPlayer) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerStop(%08x)", psmfPlayer); + INFO_LOG(HLE, "scePsmfPlayerStop(%08x)", psmfPlayer); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (psmfplayer) psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; @@ -754,18 +758,17 @@ int scePsmfPlayerBreak(u32 psmfPlayer) int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerSetPsmf(%08x, %s)", psmfPlayer, filename); - PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (psmfplayer) { + INFO_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; psmfplayer->mediaengine->loadFile(filename); psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); } else { - ERROR_LOG(HLE, "psmfplayer null in scePsmfPlayerSetPsmf"); + INFO_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s): invalid psmf player", psmfPlayer, filename); } return 0; @@ -773,18 +776,18 @@ int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerSetPsmfCB(%08x, %s)", psmfPlayer, filename); - + // TODO: hleCheckCurrentCallbacks? PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (psmfplayer) { + INFO_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; psmfplayer->mediaengine->loadFile(filename); psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); } else { - ERROR_LOG(HLE, "psmfplayer null in scePsmfPlayerSetPsmfCB"); + INFO_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s): invalid psmf player", psmfPlayer, filename); } return 0; @@ -792,13 +795,13 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) int scePsmfPlayerGetAudioOutSize(u32 psmfPlayer) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerGetAudioOutSize(%08x)", psmfPlayer); + WARN_LOG(HLE, "scePsmfPlayerGetAudioOutSize(%08x)", psmfPlayer); return audioSamplesBytes; } int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerStart(%08x, %08x, %08x)", psmfPlayer, psmfPlayerData, initPts); + WARN_LOG(HLE, "UNIMPL scePsmfPlayerStart(%08x, %08x, %08x)", psmfPlayer, psmfPlayerData, initPts); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { @@ -838,28 +841,29 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) int scePsmfPlayerDelete(u32 psmfPlayer) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerDelete(%08x)", psmfPlayer); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (psmfplayer) { - psmfplayer->status = PSMF_PLAYER_STATUS_NONE; + INFO_LOG(HLE, "scePsmfPlayerDelete(%08x)", psmfPlayer); delete psmfplayer; psmfPlayerMap.erase(psmfPlayer); + } else { + ERROR_LOG(HLE, "scePsmfPlayerDelete(%08x): invalid psmf player", psmfPlayer); } return 0; } int scePsmfPlayerUpdate(u32 psmfPlayer) { - DEBUG_LOG(HLE, "scePsmfPlayerUpdate(%08x)", psmfPlayer); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerUpdate - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerUpdate(%08x): invalid psmf player", psmfPlayer); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfPlayerUpdate(%08x)", psmfPlayer); if (psmfplayer->psmfPlayerAvcAu.pts > 0) { if (psmfplayer->psmfPlayerAvcAu.pts >= psmfplayer->psmfPlayerLastTimestamp) { - INFO_LOG(HLE,"video end reach"); + INFO_LOG(HLE, "video end reached"); psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING_FINISHED; } } @@ -877,13 +881,13 @@ int scePsmfPlayerReleasePsmf(u32 psmfPlayer) int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) { - DEBUG_LOG(HLE, "scePsmfPlayerGetVideoData(%08x, %08x)", psmfPlayer, videoDataAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetVideoData - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetVideoData(%08x, %08x): invalid psmf player", psmfPlayer, videoDataAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfPlayerGetVideoData(%08x, %08x)", psmfPlayer, videoDataAddr); if (Memory::IsValidAddress(videoDataAddr)) { int frameWidth = Memory::Read_U32(videoDataAddr); u32 displaybuf = Memory::Read_U32(videoDataAddr + 4); @@ -910,13 +914,13 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) int scePsmfPlayerGetAudioData(u32 psmfPlayer, u32 audioDataAddr) { - DEBUG_LOG(HLE, "scePsmfPlayerGetAudioData(%08x, %08x)", psmfPlayer, audioDataAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetAudioData - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetAudioData(%08x, %08x): invalid psmf player", psmfPlayer, audioDataAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfPlayerGetAudioData(%08x, %08x)", psmfPlayer, audioDataAddr); if (Memory::IsValidAddress(audioDataAddr)) { Memory::Memset(audioDataAddr, 0, audioSamplesBytes); psmfplayer->mediaengine->getAudioSamples(Memory::GetPointer(audioDataAddr)); @@ -929,7 +933,7 @@ int scePsmfPlayerGetCurrentStatus(u32 psmfPlayer) { PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentStatus(%08x) - invalid psmf", psmfPlayer); + ERROR_LOG(HLE, "scePsmfPlayerGetCurrentStatus(%08x): invalid psmf player", psmfPlayer); return ERROR_PSMF_NOT_FOUND; } DEBUG_LOG(HLE, "%d=scePsmfPlayerGetCurrentStatus(%08x)", psmfplayer->status, psmfPlayer); @@ -938,18 +942,17 @@ int scePsmfPlayerGetCurrentStatus(u32 psmfPlayer) u32 scePsmfPlayerGetCurrentPts(u32 psmfPlayer, u32 currentPtsAddr) { - DEBUG_LOG(HLE, "scePsmfPlayerGetCurrentPts(%08x, %08x)", psmfPlayer , currentPtsAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentPts - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetCurrentPts(%08x, %08x): invalid psmf player", psmfPlayer, currentPtsAddr); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfPlayerGetCurrentPts(%08x, %08x)", psmfPlayer, currentPtsAddr); if (psmfplayer->status < PSMF_PLAYER_STATUS_STANDBY) { return ERROR_PSMFPLAYER_NOT_INITIALIZED; } if (Memory::IsValidAddress(currentPtsAddr)) { - //Comment out until psmfPlayerAvcAu.pts start increasing correctly, Ultimate Ghosts N Goblins relies on it . Memory::Write_U32(psmfplayer->psmfPlayerAvcAu.pts, currentPtsAddr); } return 0; @@ -957,16 +960,17 @@ u32 scePsmfPlayerGetCurrentPts(u32 psmfPlayer, u32 currentPtsAddr) u32 scePsmfPlayerGetPsmfInfo(u32 psmfPlayer, u32 psmfInfoAddr) { - ERROR_LOG(HLE, "scePsmfPlayerGetPsmfInfo(%08x, %08x)", psmfPlayer , psmfInfoAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetPsmfInfo - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetPsmfInfo(%08x, %08x): invalid psmf player", psmfPlayer, psmfInfoAddr); return ERROR_PSMF_NOT_FOUND; } if (psmfplayer->status < PSMF_PLAYER_STATUS_STANDBY) { + ERROR_LOG(HLE, "scePsmfPlayerGetPsmfInfo(%08x, %08x): not initialized", psmfPlayer, psmfInfoAddr); return ERROR_PSMFPLAYER_NOT_INITIALIZED; } + WARN_LOG(HLE, "scePsmfPlayerGetPsmfInfo(%08x, %08x)", psmfPlayer, psmfInfoAddr); if (Memory::IsValidAddress(psmfInfoAddr)) { Memory::Write_U32(psmfplayer->psmfPlayerLastTimestamp, psmfInfoAddr); Memory::Write_U32(psmfplayer->videoStreamNum, psmfInfoAddr + 4); @@ -981,12 +985,12 @@ u32 scePsmfPlayerGetPsmfInfo(u32 psmfPlayer, u32 psmfInfoAddr) u32 scePsmfPlayerGetCurrentPlayMode(u32 psmfPlayer, u32 playModeAddr, u32 playSpeedAddr) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x)", psmfPlayer , playModeAddr, playSpeedAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentPlayMode - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x): invalid psmf player", psmfPlayer, playModeAddr, playSpeedAddr); return ERROR_PSMF_NOT_FOUND; } + WARN_LOG(HLE, "scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x)", psmfPlayer, playModeAddr, playSpeedAddr); if (Memory::IsValidAddress(playModeAddr)) { Memory::Write_U64(psmfplayer->playMode, playModeAddr); } @@ -998,12 +1002,12 @@ u32 scePsmfPlayerGetCurrentPlayMode(u32 psmfPlayer, u32 playModeAddr, u32 playSp u32 scePsmfPlayerGetCurrentVideoStream(u32 psmfPlayer, u32 videoCodecAddr, u32 videoStreamNumAddr) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x)", psmfPlayer , videoCodecAddr, videoStreamNumAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentVideoStream - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x): invalid psmf player", psmfPlayer, videoCodecAddr, videoStreamNumAddr); return ERROR_PSMF_NOT_FOUND; } + WARN_LOG(HLE, "scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x)", psmfPlayer, videoCodecAddr, videoStreamNumAddr); if (Memory::IsValidAddress(videoCodecAddr)) { Memory::Write_U64(psmfplayer->videoCodec, videoCodecAddr); } @@ -1015,12 +1019,12 @@ u32 scePsmfPlayerGetCurrentVideoStream(u32 psmfPlayer, u32 videoCodecAddr, u32 v u32 scePsmfPlayerGetCurrentAudioStream(u32 psmfPlayer, u32 audioCodecAddr, u32 audioStreamNumAddr) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x)", psmfPlayer , audioCodecAddr, audioStreamNumAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerGetCurrentAudioStream - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x): invalid psmf player", psmfPlayer, audioCodecAddr, audioStreamNumAddr); return ERROR_PSMF_NOT_FOUND; } + WARN_LOG(HLE, "scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x)", psmfPlayer, audioCodecAddr, audioStreamNumAddr); if (Memory::IsValidAddress(audioCodecAddr)) { Memory::Write_U64(psmfplayer->audioCodec, audioCodecAddr); } @@ -1041,13 +1045,13 @@ int scePsmfPlayerSetTempBuf(u32 psmfPlayer, u32 tempBufAddr, u32 tempBufSize) u32 scePsmfPlayerChangePlayMode(u32 psmfPlayer, int playMode, int playSpeed) { - ERROR_LOG(HLE, "scePsmfPlayerChangePlayMode(%08x, %i, %i)", psmfPlayer , playMode, playSpeed); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerChangePlayMode - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerChangePlayMode(%08x, %i, %i): invalid psmf player", psmfPlayer, playMode, playSpeed); return ERROR_PSMF_NOT_FOUND; } + WARN_LOG(HLE, "scePsmfPlayerChangePlayMode(%08x, %i, %i)", psmfPlayer, playMode, playSpeed); psmfplayer->playMode = playMode; psmfplayer->playSpeed = playSpeed; return 0; @@ -1055,37 +1059,37 @@ u32 scePsmfPlayerChangePlayMode(u32 psmfPlayer, int playMode, int playSpeed) u32 scePsmfPlayerSelectAudio(u32 psmfPlayer) { - ERROR_LOG(HLE, "scePsmfPlayerSelectAudio(%08x)", psmfPlayer); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerChangePlayMode - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerSelectAudio(%08x): invalid psmf player", psmfPlayer); return ERROR_PSMF_NOT_FOUND; } + ERROR_LOG(HLE, "scePsmfPlayerSelectAudio(%08x)", psmfPlayer); psmfplayer->audioStreamNum++; return 0; } u32 scePsmfPlayerSelectVideo(u32 psmfPlayer) { - ERROR_LOG(HLE, "scePsmfPlayerSelectVideo(%08x)", psmfPlayer); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerSelectVideo - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerSelectVideo(%08x): invalid psmf player", psmfPlayer); return ERROR_PSMF_NOT_FOUND; } + ERROR_LOG(HLE, "scePsmfPlayerSelectVideo(%08x)", psmfPlayer); psmfplayer->videoStreamNum++; return 0; } u32 scePsmfPlayerSelectSpecificVideo(u32 psmfPlayer, int videoCodec, int videoStreamNum) { - ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i)", psmfPlayer , videoCodec, videoStreamNum); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificVideo - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): invalid psmf player", psmfPlayer, videoCodec, videoStreamNum); return ERROR_PSMF_NOT_FOUND; } + ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i)", psmfPlayer, videoCodec, videoStreamNum); psmfplayer->videoCodec = videoCodec; psmfplayer->videoStreamNum = videoStreamNum; psmfplayer->mediaengine->setVideoStream(videoStreamNum); @@ -1094,13 +1098,13 @@ u32 scePsmfPlayerSelectSpecificVideo(u32 psmfPlayer, int videoCodec, int videoSt u32 scePsmfPlayerSelectSpecificAudio(u32 psmfPlayer, int audioCodec, int audioStreamNum) { - ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i)", psmfPlayer , audioCodec, audioStreamNum); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificAudio - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): invalid psmf player", psmfPlayer, audioCodec, audioStreamNum); return ERROR_PSMF_NOT_FOUND; } + ERROR_LOG(HLE, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i)", psmfPlayer, audioCodec, audioStreamNum); psmfplayer->audioCodec = audioCodec; psmfplayer->audioStreamNum = audioStreamNum; psmfplayer->mediaengine->setAudioStream(audioStreamNum); @@ -1111,18 +1115,20 @@ u32 scePsmfPlayerConfigPlayer(u32 psmfPlayer, int configMode, int configAttr) { PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { - ERROR_LOG(HLE, "scePsmfPlayerConfigPlayer - invalid psmf"); + ERROR_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, %i, %i): invalid psmf player", psmfPlayer, configMode, configAttr); return ERROR_PSMF_NOT_FOUND; } if (configMode == PSMF_PLAYER_CONFIG_MODE_LOOP) { + INFO_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, loop, %i)", psmfPlayer, configAttr); videoLoopStatus = configAttr; } else if (configMode == PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE) { + INFO_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, pixelType, %i)", psmfPlayer, configAttr); // Does -1 mean default or something? if (configAttr != -1) { videoPixelMode = configAttr; } } else { - ERROR_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, %i, %i): unknown parameter", psmfPlayer, configMode, configAttr); + ERROR_LOG_REPORT(HLE, "scePsmfPlayerConfigPlayer(%08x, %i, %i): unknown parameter", psmfPlayer, configMode, configAttr); } return 0; diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index ae0f2c021b..1b35a1f1dd 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -56,7 +56,6 @@ static AVPixelFormat getSwsFormat(int pspFormat) return AV_PIX_FMT_BGR444LE; case TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888: return AV_PIX_FMT_RGBA; - default: ERROR_LOG(ME, "Unknown pixel format"); return (AVPixelFormat)0; @@ -136,9 +135,20 @@ void MediaEngine::closeMedia() { int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) { - MediaEngine *mpeg = (MediaEngine*)opaque; + MediaEngine *mpeg = (MediaEngine *)opaque; + if ((u32)mpeg->m_decodeNextPos > (u32)mpeg->m_streamSize) + return -1; + int size = std::min(mpeg->m_bufSize, buf_size); - size = std::max(std::min((mpeg->m_readSize - mpeg->m_decodeNextPos), size), 0); + int available = mpeg->m_readSize - mpeg->m_decodeNextPos; + int remaining = mpeg->m_streamSize - mpeg->m_decodeNextPos; + + // There's more in the file, and there's not as much as requested available. + // Return nothing. Partial packets will cause artifacts or green frames. + if (available < remaining && size > available) + return 0; + + size = std::min(size, remaining); if (size > 0) memcpy(buf, mpeg->m_pdata + mpeg->m_decodeNextPos, size); mpeg->m_decodeNextPos += size; @@ -158,8 +168,15 @@ int64_t _MpegSeekbuffer(void *opaque, int64_t offset, int whence) case SEEK_END: mpeg->m_decodeNextPos = mpeg->m_streamSize - (u32)offset; break; + +#ifdef USE_FFMPEG + // Don't seek, just return the full size. + // Returning this means FFmpeg won't think frames are truncated if we don't have them yet. + case AVSEEK_SIZE: + return mpeg->m_streamSize; +#endif } - return offset; + return mpeg->m_decodeNextPos; } #ifdef _DEBUG @@ -283,7 +300,7 @@ int MediaEngine::addStreamData(u8* buffer, int addSize) { if (size > 0 && m_pdata) { memcpy(m_pdata + m_readSize, buffer, size); m_readSize += size; - if (!m_pFormatCtx && m_readSize > 0x2000) + if (!m_pFormatCtx && (m_readSize > 0x20000 || m_readSize >= m_streamSize)) openContext(); if (m_demux) { m_demux->setReadSize(m_readSize); @@ -414,6 +431,46 @@ bool MediaEngine::stepVideo(int videoPixelMode) { #endif // USE_FFMPEG } +// Helpers that null out alpha (which seems to be the case on the PSP.) +// Some games depend on this, for example Sword Art Online (doesn't clear A's from buffer.) + +inline void writeVideoLineRGBA(void *destp, const void *srcp, int width) { + // TODO: Use SSE/NEON, investigate why AV_PIX_FMT_RGB0 does not work. + u32 *dest = (u32 *)destp; + const u32 *src = (u32 *)srcp; + + u32 mask = 0x00FFFFFF; + for (int i = 0; i < width; ++i) { + dest[i] = src[i] & mask; + } +} + +inline void writeVideoLineABGR5650(void *destp, const void *srcp, int width) { + memcpy(destp, srcp, width * sizeof(u16)); +} + +inline void writeVideoLineABGR5551(void *destp, const void *srcp, int width) { + // TODO: Use SSE/NEON. + u16 *dest = (u16 *)destp; + const u16 *src = (u16 *)srcp; + + u16 mask = 0x7FFF; + for (int i = 0; i < width; ++i) { + dest[i] = src[i] & mask; + } +} + +inline void writeVideoLineABGR4444(void *destp, const void *srcp, int width) { + // TODO: Use SSE/NEON. + u16 *dest = (u16 *)destp; + const u16 *src = (u16 *)srcp; + + u16 mask = 0x0FFF; + for (int i = 0; i < width; ++i) { + dest[i] = src[i] & mask; + } +} + int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) { if ((!m_pFrame)||(!m_pFrameRGB)) return false; @@ -423,14 +480,12 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) int height = m_desHeight; int width = m_desWidth; u8 *imgbuf = buffer; - u8 *data = m_pFrameRGB->data[0]; - u16 *imgbuf16 = (u16 *)buffer; - u16 *data16 = (u16 *)data; + const u8 *data = m_pFrameRGB->data[0]; switch (videoPixelMode) { case TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888: for (int y = 0; y < height; y++) { - memcpy(imgbuf, data, width * sizeof(u32)); + writeVideoLineRGBA(imgbuf, data, width); data += width * sizeof(u32); imgbuf += frameWidth * sizeof(u32); } @@ -439,7 +494,7 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) case TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650: for (int y = 0; y < height; y++) { - memcpy(imgbuf, data, width * sizeof(u16)); + writeVideoLineABGR5650(imgbuf, data, width); data += width * sizeof(u16); imgbuf += frameWidth * sizeof(u16); } @@ -448,20 +503,18 @@ int MediaEngine::writeVideoImage(u8* buffer, int frameWidth, int videoPixelMode) case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR5551: for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - *imgbuf16++ = *data16++ | (1 << 15); - } - imgbuf16 += (frameWidth - width); + writeVideoLineABGR5551(imgbuf, data, width); + data += width * sizeof(u16); + imgbuf += frameWidth * sizeof(u16); } videoImageSize = frameWidth * sizeof(u16) * height; break; case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR4444: for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - *imgbuf16++ = *data16++ | (0xF << 12); - } - imgbuf16 += (frameWidth - width); + writeVideoLineABGR4444(imgbuf, data, width); + data += width * sizeof(u16); + imgbuf += frameWidth * sizeof(u16); } videoImageSize = frameWidth * sizeof(u16) * height; break; @@ -483,9 +536,7 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP int videoImageSize = 0; // lock the image size u8 *imgbuf = buffer; - u8 *data = m_pFrameRGB->data[0]; - u16 *imgbuf16 = (u16 *)buffer; - u16 *data16 = (u16 *)data; + const u8 *data = m_pFrameRGB->data[0]; if (width > m_desWidth - xpos) width = m_desWidth - xpos; @@ -496,7 +547,7 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP case TPSM_PIXEL_STORAGE_MODE_32BIT_ABGR8888: data += (ypos * m_desWidth + xpos) * sizeof(u32); for (int y = 0; y < height; y++) { - memcpy(imgbuf, data, width * sizeof(u32)); + writeVideoLineRGBA(imgbuf, data, width); data += m_desWidth * sizeof(u32); imgbuf += frameWidth * sizeof(u32); } @@ -506,7 +557,7 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP case TPSM_PIXEL_STORAGE_MODE_16BIT_BGR5650: data += (ypos * m_desWidth + xpos) * sizeof(u16); for (int y = 0; y < height; y++) { - memcpy(imgbuf, data, width * sizeof(u16)); + writeVideoLineABGR5650(imgbuf, data, width); data += m_desWidth * sizeof(u16); imgbuf += frameWidth * sizeof(u16); } @@ -516,11 +567,9 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR5551: data += (ypos * m_desWidth + xpos) * sizeof(u16); for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - *imgbuf16++ = *data16++ | (1 << 15); - } - imgbuf16 += (frameWidth - width); - data16 += (m_desWidth - width); + writeVideoLineABGR5551(imgbuf, data, width); + data += m_desWidth * sizeof(u16); + imgbuf += frameWidth * sizeof(u16); } videoImageSize = frameWidth * sizeof(u16) * m_desHeight; break; @@ -528,11 +577,9 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP case TPSM_PIXEL_STORAGE_MODE_16BIT_ABGR4444: data += (ypos * m_desWidth + xpos) * sizeof(u16); for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - *imgbuf16++ = *data16++ | (0xF << 12); - } - imgbuf16 += (frameWidth - width); - data16 += (m_desWidth - width); + writeVideoLineABGR4444(imgbuf, data, width); + data += m_desWidth * sizeof(u16); + imgbuf += frameWidth * sizeof(u16); } videoImageSize = frameWidth * sizeof(u16) * m_desHeight; break; diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index 74cccb80b9..d61cb61298 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -516,6 +516,11 @@ namespace MIPSComp if (js.HasUnknownPrefix()) DISABLE; + // Pre-processing: Eliminate silly no-op VMOVs, common in Wipeout Pure + if (((op >> 16) & 0x1f) == 0 && _VS == _VD && js.HasNoPrefix()) { + return; + } + VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 54c89a9488..ec8d46796d 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -96,6 +96,10 @@ struct ArmJitState } return false; } + bool HasNoPrefix() const { + return (prefixDFlag & PREFIX_KNOWN) && (prefixSFlag & PREFIX_KNOWN) && (prefixTFlag & PREFIX_KNOWN) && (prefixS == 0xE4 && prefixT == 0xE4 && prefixD == 0); + } + void EatPrefix() { if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) { prefixSFlag = PREFIX_KNOWN_DIRTY; diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index 24aa220e57..4825bd980f 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -632,6 +632,11 @@ void Jit::Comp_VV2Op(u32 op) { if (js.HasUnknownPrefix()) DISABLE; + // Pre-processing: Eliminate silly no-op VMOVs, common in Wipeout Pure + if (((op >> 16) & 0x1f) == 0 && _VS == _VD && js.HasNoPrefix()) { + return; + } + VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 0182705ee1..42deb55b7b 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -111,6 +111,9 @@ struct JitState } return false; } + bool HasNoPrefix() const { + return (prefixDFlag & PREFIX_KNOWN) && (prefixSFlag & PREFIX_KNOWN) && (prefixTFlag & PREFIX_KNOWN) && (prefixS == 0xE4 && prefixT == 0xE4 && prefixD == 0); + } void EatPrefix() { if ((prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4) { prefixSFlag = PREFIX_KNOWN_DIRTY; diff --git a/Core/System.cpp b/Core/System.cpp index dbafe42f57..d4d4e22d87 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -97,7 +97,8 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) // TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly std::string filename = coreParameter.fileToStart; - if (!LoadFile(filename, error_string)) { + if (!LoadFile(filename, error_string) || coreState == CORE_POWERDOWN) + { pspFileSystem.Shutdown(); CoreTiming::Shutdown(); __KernelShutdown(); diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 31807904d6..dc3262788b 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -326,52 +326,6 @@ static const AtlasChar *PPGeGetChar(const AtlasFont &atlasfont, unsigned int cva return c; } -static float NextWordWidth(UTF8 utf, const AtlasFont &atlasfont, float scale) { - float w = 0.0; - bool finished = false; - while (!utf.end() && !finished) { - u32 cval = utf.next(); - const AtlasChar *ch = PPGeGetChar(atlasfont, cval); - if (!ch) { - continue; - } - - switch (cval) { - // TODO: This list of punctuation is very incomplete. - case ',': - case '.': - case ':': - case '!': - case ')': - case '?': - case 0x3001: // IDEOGRAPHIC COMMA - case 0x3002: // IDEOGRAPHIC FULL STOP - case 0x06D4: // ARABIC FULL STOP - case 0xFF01: // FULLWIDTH EXCLAMATION MARK - case 0xFF09: // FULLWIDTH RIGHT PARENTHESIS - case 0xFF1F: // FULLWIDTH QUESTION MARK - // Count this character (punctuation is so clingy), but then we're done. - w += ch->wx * scale; - finished = true; - break; - - case ' ': - case '\t': - case '\r': - case '\n': - case 0x3000: // IDEOGRAPHIC SPACE - finished = true; - break; - - default: - w += ch->wx * scale; - break; - } - } - - return w; -} - // Break a single text string into mutiple lines. static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont, float x, float y, int align, float scale, int wrapType, float wrapWidth, bool dryRun) @@ -384,12 +338,14 @@ static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont, wrapWidth = 480.f; } - // used for replacing with ellipsis + // used for replacing with ellipses float wrapCutoff = 8.0f; const AtlasChar *dot = PPGeGetChar(atlasfont, '.'); if (dot) { wrapCutoff = dot->wx * scale * 3.0f; } + float threshold = sx + wrapWidth - wrapCutoff; + //const float wrapGreyZone = 2.0f; // Grey zone for punctuations at line ends int numLines = 1; @@ -398,52 +354,175 @@ static AtlasTextMetrics BreakLines(const char *text, const AtlasFont &atlasfont, for (UTF8 utf(text); !utf.end(); ) { float lineWidth = 0; + bool skipRest = false; while (!utf.end()) { - uint32_t cval = utf.next(); - if (cval == '\n') { - ++numLines; - break; - } - if (cval == '\r') { - // We simply ignore this. - continue; - } - const AtlasChar *c = PPGeGetChar(atlasfont, cval); - if (c) + UTF8 utfWord(utf); + float nextWidth = 0; + float spaceWidth = 0; + int numChars = 0; + bool finished = false; + while (!utfWord.end() && !finished) { - if (wrapType > 0) - { - float nextWidth = NextWordWidth(utf, atlasfont, scale); - if (lineWidth + nextWidth > wrapWidth) { - if (wrapType & PPGE_LINE_WRAP_WORD) { - // TODO: Should check if we have had at least one other word instead. - if (lineWidth > 0) { - ++numLines; + UTF8 utfPrev = utfWord; + u32 cval = utfWord.next(); + const AtlasChar *ch = PPGeGetChar(atlasfont, cval); + if (!ch) { + continue; + } + + switch (cval) { + // TODO: This list of punctuation is very incomplete. + case ',': + case '.': + case ':': + case '!': + case ')': + case '?': + case 0x3001: // IDEOGRAPHIC COMMA + case 0x3002: // IDEOGRAPHIC FULL STOP + case 0x06D4: // ARABIC FULL STOP + case 0xFF01: // FULLWIDTH EXCLAMATION MARK + case 0xFF09: // FULLWIDTH RIGHT PARENTHESIS + case 0xFF1F: // FULLWIDTH QUESTION MARK + // Count this character (punctuation is so clingy), but then we're done. + ++numChars; + nextWidth += ch->wx * scale; + finished = true; + break; + + case ' ': + case 0x3000: // IDEOGRAPHIC SPACE + spaceWidth += ch->wx * scale; + finished = true; + break; + + case '\t': + case '\r': + case '\n': + // Ignore this character and we're done. + finished = true; + break; + + default: + { + // CJK characters can be wrapped more freely. + bool isCJK = (cval >= 0x1100 && cval <= 0x11FF); // Hangul Jamo. + isCJK = isCJK || (cval >= 0x2E80 && cval <= 0x2FFF); // Kangxi Radicals etc. +#if 0 + isCJK = isCJK || (cval >= 0x3040 && cval <= 0x31FF); // Hiragana, Katakana, Hangul Compatibility Jamo etc. + isCJK = isCJK || (cval >= 0x3200 && cval <= 0x32FF); // CJK Enclosed + isCJK = isCJK || (cval >= 0x3300 && cval <= 0x33FF); // CJK Compatibility + isCJK = isCJK || (cval >= 0x3400 && cval <= 0x4DB5); // CJK Unified Ideographs Extension A +#else + isCJK = isCJK || (cval >= 0x3040 && cval <= 0x4DB5); // Above collapsed +#endif + isCJK = isCJK || (cval >= 0x4E00 && cval <= 0x9FBB); // CJK Unified Ideographs + isCJK = isCJK || (cval >= 0xAC00 && cval <= 0xD7AF); // Hangul Syllables + isCJK = isCJK || (cval >= 0xF900 && cval <= 0xFAD9); // CJK Compatibility Ideographs + isCJK = isCJK || (cval >= 0x20000 && cval <= 0x2A6D6); // CJK Unified Ideographs Extension B + isCJK = isCJK || (cval >= 0x2F800 && cval <= 0x2FA1D); // CJK Compatibility Supplement + if (isCJK) { + if (numChars > 0) { + utfWord = utfPrev; + finished = true; break; - } - } - if (wrapType & PPGE_LINE_USE_ELLIPSIS) { - if (nextWidth >= wrapCutoff) { - // TODO: Truncate the word with an ellipsis. - // The word is not too short. - } + } } } + ++numChars; + nextWidth += ch->wx * scale; + break; } + } + + bool useEllipsis = false; + if (wrapType > 0) + { + if (lineWidth + nextWidth > wrapWidth || skipRest) + { + if (wrapType & PPGE_LINE_WRAP_WORD) { + // TODO: Should check if we have had at least one other word instead. + if (lineWidth > 0) { + ++numLines; + break; + } + } + if (wrapType & PPGE_LINE_USE_ELLIPSIS) { + useEllipsis = true; + if (skipRest) { + numChars = 0; + } else if (nextWidth < wrapCutoff) { + // The word is too short, so just backspace! + x = threshold; + } + nextWidth = 0; + spaceWidth = 0; + lineWidth = wrapWidth; + } + } + } + for (int i = 0; i < numChars; ++i) + { + u32 cval = utf.next(); + const AtlasChar *c = PPGeGetChar(atlasfont, cval); + if (c) + { + if (useEllipsis && x >= threshold && dot) + { + if (!dryRun) + { + AtlasCharVertex cv; + // Replace the following part with an ellipsis. + cv.x = x + dot->ox * scale; + cv.y = y + dot->oy * scale; + cv.c = dot; + char_one_line.push_back(cv); + cv.x += dot->wx * scale; + char_one_line.push_back(cv); + cv.x += dot->wx * scale; + char_one_line.push_back(cv); + } + skipRest = true; + break; + } + if (!dryRun) + { + AtlasCharVertex cv; + cv.x = x + c->ox * scale; + cv.y = y + c->oy * scale; + cv.c = c; + char_one_line.push_back(cv); + } + x += c->wx * scale; + } + } + lineWidth += nextWidth; + + u32 cval = utf.next(); + if (spaceWidth > 0) + { if (!dryRun) { + // No need to check c. + const AtlasChar *c = PPGeGetChar(atlasfont, cval); AtlasCharVertex cv; cv.x = x + c->ox * scale; cv.y = y + c->oy * scale; cv.c = c; char_one_line.push_back(cv); } - - float ww = c->wx * scale; - lineWidth += ww; - x += ww; + x += spaceWidth; + lineWidth += spaceWidth; + if (wrapType > 0 && lineWidth > wrapWidth) { + lineWidth = wrapWidth; + } } + else if (cval == '\n') { + ++numLines; + break; + } + utf = utfWord; } y += lineHeight; x = sx; diff --git a/Core/Util/ppge_atlas.cpp b/Core/Util/ppge_atlas.cpp index 9909e919c9..04bc2243f8 100644 --- a/Core/Util/ppge_atlas.cpp +++ b/Core/Util/ppge_atlas.cpp @@ -34620,7 +34620,7 @@ const AtlasCharRange font_UBUNTU24_ranges[] = { }; const AtlasFont font_UBUNTU24 = { 4.531250f, // padding - 35.562500f, // height + 31.562500f, // height 26.000000f, // ascend 0.750000f, // distslope font_UBUNTU24_chardata, @@ -34633,7 +34633,7 @@ const AtlasFont *ppge_fonts[1] = { }; const AtlasImage ppge_images[4] = { {0.033447f, 0.000244f, 0.048096f, 0.014893f, 31, 31, "I_CROSS"}, - {0.000244f, 0.000244f, 0.015381f, 0.015381f, 32, 32, "I_CIRCLE"}, + {0.000244f, 0.000244f, 0.015881f, 0.015881f, 32, 32, "I_CIRCLE"}, {0.066162f, 0.000244f, 0.079834f, 0.013916f, 29, 29, "I_SQUARE"}, {0.016357f, 0.000244f, 0.032471f, 0.013916f, 34, 29, "I_TRIANGLE"}, }; diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index e7fe804f83..180c2530bc 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -1030,20 +1030,17 @@ void TextureCache::SetTexture() { entry->numInvalidated++; gpuStats.numTextureInvalidations++; INFO_LOG(G3D, "Texture different or overwritten, reloading at %08x", texaddr); - if (entry->texture == lastBoundTexture) { - lastBoundTexture = -1; - } if (doDelete) { - // TODO: This stuff is missing some check, its causes corruption. See issue #2222 . - /* - if (entry->maxLevel == maxLevel && entry->dim == (gstate.texsize[0] & 0xF0F)) { + if (entry->maxLevel == maxLevel && entry->dim == (gstate.texsize[0] & 0xF0F) && entry->format == format && g_Config.iTexScalingLevel <= 1) { // Actually, if size and number of levels match, let's try to avoid deleting and recreating. // Instead, let's use glTexSubImage to replace the images. replaceImages = true; } else { + if (entry->texture == lastBoundTexture) { + lastBoundTexture = -1; + } glDeleteTextures(1, &entry->texture); - }*/ - glDeleteTextures(1, &entry->texture); + } } if (entry->status == TexCacheEntry::STATUS_RELIABLE) { entry->status = TexCacheEntry::STATUS_HASHING; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index cdec86b448..9c20120ef2 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -1047,9 +1047,9 @@ u32 TransformDrawEngine::ComputeHash() { u32 TransformDrawEngine::ComputeFastDCID() { u32 hash = 0; for (int i = 0; i < numDrawCalls; i++) { - hash ^= (u32)drawCalls[i].verts; + hash ^= (u32)(uintptr_t)drawCalls[i].verts; hash = __rotl(hash, 13); - hash ^= (u32)drawCalls[i].inds; + hash ^= (u32)(uintptr_t)drawCalls[i].inds; hash = __rotl(hash, 13); hash ^= (u32)drawCalls[i].vertType; hash = __rotl(hash, 13); diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index 7161d85b9c..384b1f5896 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -22,7 +22,7 @@ win32 { LIBS += -lCore -lCommon -lNative -lwinmm -lws2_32 } linux { - LIBS += -L. -lCore -lCommon -lNative + LIBS += -L. -lCore -lCommon -lNative -ldl PRE_TARGETDEPS += ./libCommon.a ./libCore.a ./libNative.a !mobile_platform { CONFIG += link_pkgconfig diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7e087d630e..95935d1242 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -178,9 +178,17 @@ void EmuScreen::update(InputState &input) { // First translate touches into native pad input. // Do this no matter the value of g_Config.bShowTouchControls, some people // like to use invisible controls... - UpdateGamepad(input); + // Don't force on platforms that likely don't have a touchscreen, like Win32, OSX, and Linux... + // TODO: What are good ifdefs for OSX and Linux, without breaking other mobile platforms? +#ifdef _WIN32 + if(g_Config.bShowTouchControls) { +#endif + UpdateGamepad(input); - UpdateInputState(&input); + UpdateInputState(&input); +#ifdef _WIN32 + } +#endif // Then translate pad input into PSP pad input. Also, add in tilt. static const int mapping[12][2] = { diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index e408dda78c..52b703f4f4 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -269,6 +269,13 @@ void MenuScreen::render() { LaunchBrowser("http://www.ppsspp.org/"); } + // Skip the forum button if screen too small. Will be redesigned in new UI later. + if (dp_yres > 510) { + if (UIButton(GEN_ID, vlinear, w, 0, "forums.ppsspp.org", ALIGN_RIGHT)) { + LaunchBrowser("http://forums.ppsspp.org/"); + } + } + int recentW = 350; if (g_Config.recentIsos.size()) { ui_draw2d.DrawText(UBUNTU24, m->T("Recent"), -xoff, 80, 0xFFFFFFFF, ALIGN_BOTTOMLEFT); @@ -462,38 +469,34 @@ void PauseScreen::render() { UICheckBox(GEN_ID, x, y += stride, ss->T("Show FPS"), ALIGN_TOPLEFT, &g_Config.bShowFPSCounter); bool enableFrameSkip = g_Config.iFrameSkip != 0; - UICheckBox(GEN_ID, x, (y += stride) + 5, gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); - - HLinear hlinear1(x + 330, y, 20); - if (UIButton(GEN_ID, hlinear1, 90, 0, gs->T("Auto"), ALIGN_LEFT)) - g_Config.iFrameSkip = 3; - if (UIButton(GEN_ID, hlinear1, 45, 0, gs->T("-1"), ALIGN_LEFT)) - if (g_Config.iFrameSkip > 1) - g_Config.iFrameSkip -= 1; - if (UIButton(GEN_ID, hlinear1, 45, 0, gs->T("+1"), ALIGN_LEFT)) - if (g_Config.iFrameSkip < 9) - g_Config.iFrameSkip += 1; - + UICheckBox(GEN_ID, x, y += stride , gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); if (enableFrameSkip) { if (g_Config.iFrameSkip == 0) g_Config.iFrameSkip = 3; char showFrameSkip[256]; sprintf(showFrameSkip, "%s %d", gs->T("Frames :"), g_Config.iFrameSkip); - ui_draw2d.DrawText(UBUNTU24, showFrameSkip, dp_xres - 15, y - 2, 0xc0000000, ALIGN_TOPRIGHT); - ui_draw2d.DrawText(UBUNTU24, showFrameSkip, dp_xres - 15, y, 0xFF3fFF3f, ALIGN_TOPRIGHT); - } - else { + ui_draw2d.DrawText(UBUNTU24, showFrameSkip, x + 60, y += stride, 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear2(x + 220, y, 20); + if (UIButton(GEN_ID, hlinear2, 80, 0, gs->T("Auto"), ALIGN_LEFT)) + g_Config.iFrameSkip = 3; + if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("-1"), ALIGN_LEFT)) + if (g_Config.iFrameSkip > 1) + g_Config.iFrameSkip -= 1; + if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("+1"), ALIGN_LEFT)) + if (g_Config.iFrameSkip < 9) + g_Config.iFrameSkip += 1; + + } else g_Config.iFrameSkip = 0; - } // TODO: Add UI for more than one slot. HLinear hlinear2(x, y += 70, 20); - if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 125, 0, i->T("Save State"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, i->T("Save State"), ALIGN_LEFT)) { SaveState::SaveSlot(0, 0, 0); screenManager()->finishDialog(this, DR_CANCEL); } - if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 125, 0, i->T("Load State"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, i->T("Load State"), ALIGN_LEFT)) { SaveState::LoadSlot(0, 0, 0); screenManager()->finishDialog(this, DR_CANCEL); } @@ -653,7 +656,7 @@ void DeveloperScreen::render() { bool reportingEnabled = Reporting::IsEnabled(); const static std::string reportHostOfficial = "report.ppsspp.org"; - if (UICheckBox(GEN_ID, x, y += stride, s->T("Enable Compatibility Server Reports"), ALIGN_TOPLEFT, &reportingEnabled)) { + if (UICheckBox(GEN_ID, x, y += stride, d->T("Report","Enable Compatibility Server Reports"), ALIGN_TOPLEFT, &reportingEnabled)) { g_Config.sReportHost = reportingEnabled ? reportHostOfficial : ""; } @@ -709,14 +712,14 @@ void AudioScreen::render() { int columnw = 400; UICheckBox(GEN_ID, x, y += stride, a->T("Enable Sound"), ALIGN_TOPLEFT, &g_Config.bEnableSound); if (Atrac3plus_Decoder::IsInstalled() && g_Config.bEnableSound) { - UICheckBox(GEN_ID, x, y += stride, a->T("Enable Atrac3+"), ALIGN_TOPLEFT, &g_Config.bEnableAtrac3plus); + UICheckBox(GEN_ID, x + 60, y += stride, a->T("Enable Atrac3+"), ALIGN_TOPLEFT, &g_Config.bEnableAtrac3plus); } #if (defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))) || defined(ARMEABI) || defined(ARMEABI_V7A) VLinear vlinear(30, 300, 20); - if (UIButton(GEN_ID, vlinear, 400, 0, a->T("Download Atrac3+ plugin"), ALIGN_LEFT)) { + if (!Atrac3plus_Decoder::IsInstalled() && UIButton(GEN_ID, vlinear, 400, 0, a->T("Download Atrac3+ plugin"), ALIGN_LEFT)) { screenManager()->push(new PluginScreen()); } @@ -814,8 +817,10 @@ void GraphicsScreenP2::render() { if (g_Config.iAnisotropyLevel == 0) g_Config.iAnisotropyLevel = 2; - ui_draw2d.DrawText(UBUNTU24, gs->T("Level :"), x + 60, y += stride, 0xFFFFFFFF, ALIGN_LEFT); - HLinear hlinear1(x + 180, y, 20); + char showAF[256]; + sprintf(showAF, "%s %dx", gs->T("Level :"), g_Config.iAnisotropyLevel); + ui_draw2d.DrawText(UBUNTU24, showAF, x + 60, (y += stride) , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 250, y , 20); if (UIButton(GEN_ID, hlinear1, 45, 0, gs->T("2x"), ALIGN_LEFT)) g_Config.iAnisotropyLevel = 2; if (UIButton(GEN_ID, hlinear1, 45, 0, gs->T("4x"), ALIGN_LEFT)) @@ -826,35 +831,50 @@ void GraphicsScreenP2::render() { g_Config.iAnisotropyLevel = 16; y += 20; - } else { + } else g_Config.iAnisotropyLevel = 0; - } + + bool TexScaling = g_Config.iTexScalingLevel > 1; UICheckBox(GEN_ID, x, y += stride, gs->T("xBRZ Texture Scaling"), ALIGN_TOPLEFT, &TexScaling); if (TexScaling) { if (g_Config.iTexScalingLevel <= 1) g_Config.iTexScalingLevel = 2; - ui_draw2d.DrawText(UBUNTU24, gs->T("Type :"), x + 60, y += stride, 0xFFFFFFFF, ALIGN_LEFT); - HLinear hlinear1(x + 180, y, 20); + + char showType[256]; + std::string type; + + switch (g_Config.iTexScalingType) { + case 0: type = "xBRZ";break; + case 1: type = "Hybrid";break; + case 2: type = "Bicubic";break; + case 3: type = "H+B";break; + } + sprintf(showType, "%s %s", gs->T("Type :"), type.c_str()); + ui_draw2d.DrawText(UBUNTU24, showType, x + 60, (y += stride) , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 250, y, 20); if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("xBRZ"), ALIGN_LEFT)) g_Config.iTexScalingType = 0; - if (UIButton(GEN_ID, hlinear1, 150, 0, gs->T("Hybrid", "Hybrid(H)"), ALIGN_LEFT)) + if (UIButton(GEN_ID, hlinear1, 120, 0, gs->T("Hybrid", "(H)ybrid"), ALIGN_LEFT)) g_Config.iTexScalingType = 1; - if (UIButton(GEN_ID, hlinear1, 150, 0, gs->T("Bicubic", "Bicubic(B)"), ALIGN_LEFT)) + if (UIButton(GEN_ID, hlinear1, 130, 0, gs->T("Bicubic", "(B)icubic"), ALIGN_LEFT)) g_Config.iTexScalingType = 2; if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("H+B", "H+B"), ALIGN_LEFT)) g_Config.iTexScalingType = 3; - ui_draw2d.DrawText(UBUNTU24, gs->T("Level :"), x + 60, y += stride + 20, 0xFFFFFFFF, ALIGN_LEFT); - HLinear hlinear2(x + 180, y, 20); + y += 20; + char showLevel[256]; + sprintf(showLevel, "%s %dx", gs->T("Level :"), g_Config.iTexScalingLevel); + ui_draw2d.DrawText(UBUNTU24, showLevel, x + 60, (y += stride) , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear2(x + 250, y, 20); if (UIButton(GEN_ID, hlinear2, 45, 0, gs->T("2x"), ALIGN_LEFT)) g_Config.iTexScalingLevel = 2; if (UIButton(GEN_ID, hlinear2, 45, 0, gs->T("3x"), ALIGN_LEFT)) g_Config.iTexScalingLevel = 3; - UICheckBox(GEN_ID, x + 60, y += stride + 20, gs->T("Deposterize"), ALIGN_LEFT, &g_Config.bTexDeposterize); - } else { - g_Config.iTexScalingLevel = 1; - } + UICheckBox(GEN_ID, x + 60, y += stride + 20, gs->T("Deposterize"), ALIGN_LEFT, &g_Config.bTexDeposterize); + } else + g_Config.iTexScalingLevel = 1; + UIEnd(); } @@ -888,50 +908,51 @@ void GraphicsScreenP3::render() { int columnw = 400; bool FpsLimit = g_Config.iFpsLimit != 0; - UICheckBox(GEN_ID, x, y += stride, gs->T("Fps Limit"), ALIGN_TOPLEFT, &FpsLimit); + UICheckBox(GEN_ID, x, y += stride, gs->T("FPS Limit"), ALIGN_TOPLEFT, &FpsLimit); if (FpsLimit) { if (g_Config.iFpsLimit == 0) g_Config.iFpsLimit = 60; char showFps[256]; - sprintf(showFps, "%s %d", gs->T("Fps :"), g_Config.iFpsLimit); - ui_draw2d.DrawText(UBUNTU24, showFps, x + 60, (y += stride) - 5, 0xFFFFFFFF, ALIGN_LEFT); - } else { - g_Config.iFpsLimit = 0; - } - HLinear hlinear1(x + 60, y += stride, 20); - if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("Auto"), ALIGN_LEFT)) - g_Config.iFpsLimit = 60; - if (UIButton(GEN_ID, hlinear1, 60, 0, gs->T("-30"), ALIGN_LEFT)) - if(g_Config.iFpsLimit > 30){ - g_Config.iFpsLimit -= 30;} - if (UIButton(GEN_ID, hlinear1, 60, 0, gs->T("+30"), ALIGN_LEFT)) - if(g_Config.iFrameSkip != 240){ - g_Config.iFpsLimit += 30;} + sprintf(showFps, "%s %d", gs->T("FPS :"), g_Config.iFpsLimit); + ui_draw2d.DrawText(UBUNTU24, showFps, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 250, y, 20); + if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("Auto"), ALIGN_LEFT)) + g_Config.iFpsLimit = 60; + if (UIButton(GEN_ID, hlinear1, 40, 0, gs->T("-1"), ALIGN_LEFT)) + if(g_Config.iFpsLimit > 30) + g_Config.iFpsLimit -= 1; + if (UIButton(GEN_ID, hlinear1, 40, 0, gs->T("+1"), ALIGN_LEFT)) + if(g_Config.iFrameSkip != 120) + g_Config.iFpsLimit += 1; + + y += 20; + } else + g_Config.iFpsLimit = 0; bool enableFrameSkip = g_Config.iFrameSkip != 0; - UICheckBox(GEN_ID, x, y += stride + 25, gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); + UICheckBox(GEN_ID, x, y += stride , gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); if (enableFrameSkip) { if (g_Config.iFrameSkip == 0) g_Config.iFrameSkip = 3; char showFrameSkip[256]; sprintf(showFrameSkip, "%s %d", gs->T("Frames :"), g_Config.iFrameSkip); - ui_draw2d.DrawText(UBUNTU24, showFrameSkip, x + 60, (y += stride) - 5, 0xFFFFFFFF, ALIGN_LEFT); - } - else { - g_Config.iFrameSkip = 0; - } - HLinear hlinear2(x + 60, y += stride, 20); - if (UIButton(GEN_ID, hlinear2, 80, 0, gs->T("Auto"), ALIGN_LEFT)) - g_Config.iFrameSkip = 3; - if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("-1"), ALIGN_LEFT)) - if (g_Config.iFrameSkip > 1) - g_Config.iFrameSkip -= 1; - if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("+1"), ALIGN_LEFT)) - if (g_Config.iFrameSkip < 9) - g_Config.iFrameSkip += 1; + ui_draw2d.DrawText(UBUNTU24, showFrameSkip, x + 60, y += stride, 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear2(x + 250, y, 20); + if (UIButton(GEN_ID, hlinear2, 80, 0, gs->T("Auto"), ALIGN_LEFT)) + g_Config.iFrameSkip = 3; + if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("-1"), ALIGN_LEFT)) + if (g_Config.iFrameSkip > 1) + g_Config.iFrameSkip -= 1; + if (UIButton(GEN_ID, hlinear2, 40, 0, gs->T("+1"), ALIGN_LEFT)) + if (g_Config.iFrameSkip < 9) + g_Config.iFrameSkip += 1; + y += 20; + } else + g_Config.iFrameSkip = 0; + UIEnd(); } @@ -1077,7 +1098,7 @@ void SystemScreen::render() { } UICheckBox(GEN_ID, x, y += stride, s->T("Enable Cheats"), ALIGN_TOPLEFT, &g_Config.bEnableCheats); HLinear hlinear2(x, y += stride + 10, 20); - if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 150, 0, s->T("Reload Cheats"), ALIGN_TOPLEFT)) { + if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 50, 0, s->T("Reload Cheats"), ALIGN_TOPLEFT)) { g_Config.bReloadCheats = true; } if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, s->T("Language"), ALIGN_TOPLEFT)) { @@ -1357,19 +1378,28 @@ static const char * credits[] = { "", "Contributors:", "unknownbrackets", + "oioitff", "xsacha", "raven02", - "oioitff", "tpunix", "orphis", "sum2012", "mikusp", - "artart78", + "aquanull", + "The Dax", "tmaul", + "artart78", "ced2911", "soywiz", "kovensky", "xele", + "chaserhjk", + "evilcorn", + "daniel dressler", + "makotech222", + "CPkmn", + "mgaver", + "jeid3", "cinaera/BeaR", "", "Written in C++ for speed and portability", diff --git a/Windows/DSoundStream.cpp b/Windows/DSoundStream.cpp index 88d2426c6f..45047172bf 100644 --- a/Windows/DSoundStream.cpp +++ b/Windows/DSoundStream.cpp @@ -110,7 +110,7 @@ namespace DSound int lastPos; short realtimeBuffer[BUFSIZE * 2]; - DWORD WINAPI soundThread(void *) + unsigned int WINAPI soundThread(void *) { currentPos = 0; lastPos = 0; @@ -175,8 +175,7 @@ namespace DSound memset(p1,0,num1); dsBuffer->Unlock(p1,num1,0,0); totalRenderedBytes = -bufferSize; - DWORD h; - hThread = CreateThread(0,0,soundThread,0,0,&h); + hThread = (HANDLE)_beginthreadex(0, 0, soundThread, 0, 0, 0); SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); return true; } diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index e0d11a8939..135a6af73a 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -228,7 +228,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) case IDC_MEMCHECK: { - bool isRunning = !Core_IsInactive(); + bool isRunning = Core_IsActive(); if (isRunning) { SetDebugMode(true); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index cfea3c8269..76ba989006 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -7,6 +7,8 @@ #include "StringUtils.h" #include "../Globals.h" #include "EmuThread.h" +#include "WndMainWindow.h" +#include "resource.h" #include "../Core/Reporting.h" #include "../Core/MemMap.h" #include "../Core/Core.h" @@ -17,34 +19,79 @@ #include #include +#include +#pragma intrinsic(_InterlockedExchange) +class EmuThreadLockGuard +{ +public: + EmuThreadLockGuard() { emuThreadCS_.Enter(); } + ~EmuThreadLockGuard() { emuThreadCS_.Leave(); } +private: + static struct EmuThreadCS + { + EmuThreadCS() { InitializeCriticalSection(&TheCS_); } + ~EmuThreadCS() { DeleteCriticalSection(&TheCS_); } + void Enter() { EnterCriticalSection(&TheCS_); } + void Leave() { LeaveCriticalSection(&TheCS_); } + CRITICAL_SECTION TheCS_; + } emuThreadCS_; +}; + +EmuThreadLockGuard::EmuThreadCS EmuThreadLockGuard::emuThreadCS_; static HANDLE emuThread; +static long emuThreadReady; + +enum EmuTreadStatus : long +{ + THREAD_NONE = 0, + THREAD_INIT, + THREAD_CORE_LOOP, + THREAD_SHUTDOWN, + THREAD_END, +}; HANDLE EmuThread_GetThreadHandle() { + EmuThreadLockGuard lock; return emuThread; } -DWORD TheThread(LPVOID x); +unsigned int WINAPI TheThread(void *); void EmuThread_Start() { - unsigned int i; - emuThread = (HANDLE)_beginthreadex(0,0,(unsigned int (__stdcall *)(void *))TheThread,(LPVOID)0,0,&i); + EmuThreadLockGuard lock; + emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0); } void EmuThread_Stop() { // DSound_UpdateSound(); Core_Stop(); - if (WAIT_TIMEOUT == WaitForSingleObject(EmuThread_GetThreadHandle(),300)) + Core_WaitInactive(800); + if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800)) { - //MessageBox(0,"Wait for emuthread timed out, please alert the developer to possible deadlock or infinite loop in emuthread :(.",0,0); + MessageBox(MainWindow::GetHWND(),"Wait for emuthread timed out! :(\n" + "please alert the developer to possible deadlock or infinite loop in emuthread!", 0, 0); + } + { + EmuThreadLockGuard lock; + CloseHandle(emuThread); + emuThread = 0; } host->UpdateUI(); } -DWORD TheThread(LPVOID x) { +bool EmuThread_Ready() +{ + return emuThreadReady == THREAD_CORE_LOOP; +} + +unsigned int WINAPI TheThread(void *) +{ + _InterlockedExchange(&emuThreadReady, THREAD_INIT); + setCurrentThreadName("EmuThread"); std::string memstick, flash0; @@ -75,20 +122,36 @@ DWORD TheThread(LPVOID x) { INFO_LOG(BOOT, "Done."); _dbg_update_(); + if (coreState == CORE_POWERDOWN) { + INFO_LOG(BOOT, "Exit before core loop."); + goto shutdown; + } + + _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); + + if (g_Config.bBrowse) + { + PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); + //MainWindow::BrowseAndBoot(""); + } + Core_EnableStepping(FALSE); + Core_Run(); shutdown: + _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); + host = nativeHost; NativeShutdownGraphics(); NativeShutdown(); host = oldHost; - host->ShutdownGL(); + _InterlockedExchange(&emuThreadReady, THREAD_END); + //The CPU should return when a game is stopped and cleanup should be done here, //so we can restart the plugins (or load new ones) for the next game - _endthreadex(0); return 0; } diff --git a/Windows/EmuThread.h b/Windows/EmuThread.h index eedf558c40..ed1a9df08d 100644 --- a/Windows/EmuThread.h +++ b/Windows/EmuThread.h @@ -1,4 +1,22 @@ +// Copyright (c) 2013- 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 void EmuThread_Start(); -void EmuThread_Stop(); \ No newline at end of file +void EmuThread_Stop(); +bool EmuThread_Ready(); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index cedfca8d7d..23cbe0b860 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -52,7 +52,9 @@ extern InputState input_state; extern const char * getVirtualKeyName(unsigned char key); extern const char * getXinputButtonName(unsigned int button); #define TIMER_CURSORUPDATE 1 +#define TIMER_CURSORMOVEUPDATE 2 #define CURSORUPDATE_INTERVAL_MS 50 +#define CURSORUPDATE_MOVE_TIMESPAN_MS 500 namespace MainWindow { @@ -63,6 +65,10 @@ namespace MainWindow static HINSTANCE hInst; static int cursorCounter = 0; + static int prevCursorX = -1; + static int prevCursorY = -1; + static bool mouseButtonDown = false; + static bool hideCursor = false; //W32Util::LayeredWindow *layer; #define MAX_LOADSTRING 100 @@ -179,11 +185,13 @@ namespace MainWindow } void CorrectCursor() { - if (g_bFullScreen && globalUIState == UISTATE_INGAME) { + bool autoHide = g_bFullScreen && !mouseButtonDown && globalUIState == UISTATE_INGAME; + if (autoHide && hideCursor) { while (cursorCounter >= 0) { cursorCounter = ShowCursor(FALSE); } } else { + hideCursor = !autoHide; if (cursorCounter < 0) { cursorCounter = ShowCursor(TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); @@ -214,18 +222,21 @@ namespace MainWindow if (zoom < 1) zoom = 1; if (zoom > 4) zoom = 4; - RECT rc,rcOrig; + RECT rc, rcOrig; GetWindowRectAtZoom(zoom, rcOrig, rc); u32 style = WS_OVERLAPPEDWINDOW; hwndMain = CreateWindowEx(0,szWindowClass, "", style, - rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL); - SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0); - SetPlaying(0); + rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); if (!hwndMain) return FALSE; + hwndDisplay = CreateWindowEx(0, szDisplayClass, TEXT(""), WS_CHILD | WS_VISIBLE, + rcOrig.left, rcOrig.top, rcOrig.right - rcOrig.left, rcOrig.bottom - rcOrig.top, hwndMain, 0, hInstance, 0); + if (!hwndDisplay) + return FALSE; + menu = GetMenu(hwndMain); #ifdef FINAL RemoveMenu(menu,2,MF_BYPOSITION); @@ -241,20 +252,23 @@ namespace MainWindow { SetMenuInfo(GetSubMenu(menu,i),&info); } + UpdateMenus(); - hwndDisplay = CreateWindowEx(0,szDisplayClass,TEXT(""), - WS_CHILD|WS_VISIBLE, - 0,0,/*rcOrig.left,rcOrig.top,*/rcOrig.right-rcOrig.left,rcOrig.bottom-rcOrig.top,hwndMain,0,hInstance,0); - - ShowWindow(hwndMain, nCmdShow); //accept dragged files DragAcceptFiles(hwndMain, TRUE); + hideCursor = true; + SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0); + + Update(); + SetPlaying(0); + + ShowWindow(hwndMain, nCmdShow); + #if ENABLE_TOUCH RegisterTouchWindow(hwndDisplay, TWF_WANTPALM); #endif - SetFocus(hwndMain); SetFocus(hwndDisplay); return TRUE; @@ -304,6 +318,8 @@ namespace MainWindow // and as asynchronous touch events for minimal latency. case WM_LBUTTONDOWN: + // Hack: Take the opportunity to show the cursor. + mouseButtonDown = true; { lock_guard guard(input_state.lock); input_state.mouse_valid = true; @@ -324,6 +340,17 @@ namespace MainWindow case WM_MOUSEMOVE: { + // Hack: Take the opportunity to show the cursor. + mouseButtonDown = (wParam & MK_LBUTTON) != 0; + int cursorX = GET_X_LPARAM(lParam); + int cursorY = GET_Y_LPARAM(lParam); + if (abs(cursorX - prevCursorX) > 1 || abs(cursorY - prevCursorY) > 1) { + hideCursor = false; + SetTimer(hwndMain, TIMER_CURSORMOVEUPDATE, CURSORUPDATE_MOVE_TIMESPAN_MS, 0); + } + prevCursorX = cursorX; + prevCursorY = cursorY; + lock_guard guard(input_state.lock); int factor = g_Config.iWindowZoom == 1 ? 2 : 1; input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; @@ -341,6 +368,8 @@ namespace MainWindow break; case WM_LBUTTONUP: + // Hack: Take the opportunity to hide the cursor. + mouseButtonDown = false; { lock_guard guard(input_state.lock); input_state.pointer_down[0] = false; @@ -423,12 +452,22 @@ namespace MainWindow case WM_TIMER: // Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode. - CorrectCursor(); - SetTimer(hWnd, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0); - return 0; + switch (wParam) + { + case TIMER_CURSORUPDATE: + CorrectCursor(); + return 0; + case TIMER_CURSORMOVEUPDATE: + hideCursor = true; + KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); + return 0; + } + break; case WM_COMMAND: { + if (!EmuThread_Ready()) + return DefWindowProc(hWnd, message, wParam, lParam); I18NCategory *g = GetI18NCategory("Graphics"); wmId = LOWORD(wParam); @@ -714,11 +753,16 @@ namespace MainWindow case ID_EMULATION_SOUND: g_Config.bEnableSound = !g_Config.bEnableSound; break; - case ID_HELP_OPENWEBSITE: - ShellExecute(NULL, "open", "http://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL); - break; - case ID_HELP_ABOUT: + case ID_HELP_OPENWEBSITE: + ShellExecute(NULL, "open", "http://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL); + break; + + case ID_HELP_OPENFORUM: + ShellExecute(NULL, "open", "http://forums.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL); + break; + + case ID_HELP_ABOUT: DialogManager::EnableAll(FALSE); DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); DialogManager::EnableAll(TRUE); @@ -735,6 +779,9 @@ namespace MainWindow case WM_DROPFILES: { + if (!EmuThread_Ready()) + return DefWindowProc(hWnd, message, wParam, lParam); + HDROP hdrop = (HDROP)wParam; int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0); if (count != 1) @@ -760,24 +807,19 @@ namespace MainWindow break; case WM_CLOSE: - Core_Stop(); - Core_WaitInactive(200); + /* + if (g_Config.bConfirmOnQuit && __KernelIsRunning()) + if (IDYES != MessageBox(hwndMain, "A game is in progress. Are you sure you want to exit?", + "Are you sure?", MB_YESNO | MB_ICONQUESTION)) + return 0; + //*/ EmuThread_Stop(); - /* - if (g_Config.bConfirmOnQuit && CCore::IsRunning()) - { - if (IDNO==MessageBox(hwndMain,"A game is in progress. Are you sure you want to exit?","Are you sure?",MB_YESNO|MB_ICONQUESTION)) - return 1;//or 1? - else - return DefWindowProc(hWnd,message,wParam,lParam); - break; - } - else - */ return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: + KillTimer(hWnd, TIMER_CURSORUPDATE); + KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); PostQuitMessage(0); break; diff --git a/Windows/main.cpp b/Windows/main.cpp index 280520f9e4..5366a05b76 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -64,9 +64,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin hideLog = false; #endif - g_Config.Load(); - VFSRegister("", new DirectoryAssetReader("assets/")); - VFSRegister("", new DirectoryAssetReader("")); // The rest is handled in NativeInit(). for (int i = 1; i < __argc; ++i) @@ -89,6 +86,15 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } } + g_Config.Load(); + + LogManager::Init(); + LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console"); + LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); + + VFSRegister("", new DirectoryAssetReader("assets/")); + VFSRegister("", new DirectoryAssetReader("")); + //Windows, API init stuff INITCOMMONCONTROLSEX comm; comm.dwSize = sizeof(comm); @@ -97,15 +103,13 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin timeBeginPeriod(1); MainWindow::Init(_hInstance); - HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); g_hPopupMenus = LoadMenu(_hInstance, (LPCSTR)IDR_POPUPMENUS); MainWindow::Show(_hInstance, iCmdShow); - host = new WindowsHost(MainWindow::GetHWND(), MainWindow::GetDisplayHWND()); HWND hwndMain = MainWindow::GetHWND(); - HMENU menu = GetMenu(hwndMain); - + HWND hwndDisplay = MainWindow::GetDisplayHWND(); + //initialize custom controls CtrlDisAsmView::init(); CtrlMemView::init(); @@ -114,25 +118,15 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin DialogManager::AddDlg(memoryWindow[0] = new CMemoryDlg(_hInstance, hwndMain, currentDebugMIPS)); DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS)); - MainWindow::Update(); - MainWindow::UpdateMenus(); - - LogManager::Init(); - LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console"); - LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); + host = new WindowsHost(hwndMain, hwndDisplay); // Emu thread is always running! EmuThread_Start(); - if (g_Config.bBrowse) - MainWindow::BrowseAndBoot(""); - - if (!hideLog) - SetForegroundWindow(hwndMain); + HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); //so.. we're at the message pump of the GUI thread - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) //while no quit + for (MSG msg; GetMessage(&msg, NULL, 0, 0); ) // for no quit { //DSound_UpdateSound(); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index c00e33f5d3..e7bb609c13 100644 Binary files a/Windows/ppsspp.rc and b/Windows/ppsspp.rc differ diff --git a/Windows/resource.h b/Windows/resource.h index 3b7432a1a6..0195e2b168 100644 Binary files a/Windows/resource.h and b/Windows/resource.h differ diff --git a/ffmpeg b/ffmpeg index 697244c4b7..969f062d31 160000 --- a/ffmpeg +++ b/ffmpeg @@ -1 +1 @@ -Subproject commit 697244c4b79b396de86e5d7fdbf9bc4771b815e9 +Subproject commit 969f062d319ab9e3d341c6e661eedd51eefa50a2 diff --git a/lang b/lang index 9a59b4db25..cf710f2017 160000 --- a/lang +++ b/lang @@ -1 +1 @@ -Subproject commit 9a59b4db25598d735eb1ef365b6e69bff3f3e080 +Subproject commit cf710f2017db93c4019ce53a03764edf3136fa84 diff --git a/native b/native index ce962bdf95..5d098ca88b 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit ce962bdf95717c52f29c211b6b242f899dcb9174 +Subproject commit 5d098ca88bd11f0af09c95c9e91166fb82faa07b