diff --git a/.gitignore b/.gitignore index 51767a038d..7e50d2692b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ __testerror.txt __testfinish.txt __testfailure.bmp GameLogNotes.txt - +screenshots android/ui_atlas.zim android/assets/lang android/assets/flash0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3da63391c4..f322208a13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,16 +5,22 @@ project(PPSSPP) if(ANDROID) if(ARMEABI OR ARMEABI_V7A) set(ARM ON) + set(FFMPEG ON) endif() endif() +if(BLACKBERRY) + set(CMAKE_SYSTEM_NAME "QNX") +endif() + if (IOS OR BLACKBERRY) set(ARM ON) + set(FFMPEG ON) endif() if (MAEMO) set(ARM ON) - #Maemo's gcc-4.7.2 is strickt + #Maemo's gcc-4.7.2 is strict set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") endif() @@ -28,8 +34,17 @@ else() # Assume x86 set(X86 ON) endif() +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(LINUX ON) + if (NOT USING_GLES2) + # Not working yet. + #set(FFMPEG ON) + endif() +endif() + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(MACOSX ON) + set(FFMPEG ON) endif() if(ANDROID OR BLACKBERRY OR IOS OR PANDORA OR MAEMO OR MACOSX) @@ -49,7 +64,9 @@ option(MAEMO "Set to ON if targeting an Maemo (N900) device" ${MAEMO}) option(IOS "Set to ON if targeting an iOS device" ${IOS}) option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2}) option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI}) +option(FFMPEG "Set to OFF to disable FFMPEG usage" ${FFMPEG}) option(HEADLESS "Set to OFF to not generate the PPSSPPHeadless target" ${HEADLESS}) +option(USE_FFMPEG "Build with FFMPEG support (beta)" ${USE_FFMPEG}) if(ANDROID) if(NOT ANDROID_ABI) @@ -92,11 +109,7 @@ endif() include_directories("${CMAKE_SOURCE_DIR}") if(BLACKBERRY) - set(CMAKE_SYSTEM_NAME "QNX") add_definitions(-DBLACKBERRY) - if(BLACKBERRY VERSION_GREATER 10) - add_definitions(-DBLACKBERRY10) - endif() endif() if(ANDROID) @@ -454,11 +467,6 @@ elseif(IOS) ios/iCade/iCadeReaderView.m ios/iCade/iCadeState.h) set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework OpenGLES -framework UIKit -framework GLKit -framework OpenAL") - # FFMPEG - add_definitions(-DUSE_FFMPEG) - include_directories(ffmpeg/ios/universal/include) - link_directories(ffmpeg/ios/universal/lib) - set(nativeExtraLibs ${nativeExtraLibs} iconv bz2 libavformat.a libavcodec.a libswresample.a libavutil.a libswscale.a) set(TargetBin PPSSPP) elseif(USING_QT_UI) # Currently unused @@ -471,18 +479,8 @@ elseif(USING_QT_UI) elseif(BLACKBERRY) set(nativeExtra ${nativeExtra} native/base/BlackberryMain.cpp native/base/BlackberryDisplay.cpp) set(nativeExtraLibs ${nativeExtraLibs} OpenAL bps screen socket EGL) - # FFMPEG - add_definitions(-DUSE_FFMPEG) - include_directories(ffmpeg/blackberry/armv7/include) - link_directories(ffmpeg/blackberry/armv7/lib) - 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}) @@ -494,14 +492,31 @@ 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.") endif() +if(FFMPEG) + add_definitions(-DUSE_FFMPEG) + set(PLATFORM_ARCH "") + if (BLACKBERRY) + set(PLATFORM_ARCH "blackberry/armv7") + set(nativeExtraLibs ${nativeExtraLibs} iconv) + elseif(IOS) + set(PLATFORM_ARCH "ios/universal") + set(nativeExtraLibs ${nativeExtraLibs} iconv bz2) + elseif(MACOSX) + set(PLATFORM_ARCH "macosx/x86_64") + elseif(LINUX) + # Note: Only 64-bit is supported + set(PLATFORM_ARCH "linux/x86_64") + endif() + include_directories(ffmpeg/${PLATFORM_ARCH}/include) + link_directories(ffmpeg/${PLATFORM_ARCH}/lib) + set(nativeExtraLibs ${nativeExtraLibs} libavformat.a libavcodec.a libswresample.a libavutil.a libswscale.a) +endif() + if(X86) set(nativeExtra ${nativeExtra} native/base/backtrace.cpp @@ -722,7 +737,7 @@ endif() # atrac3plus.cpp used dl* functions on non-win32 platforms # Core needs to be linked with dl on these platforms -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") +if(LINUX) set(CoreExtraLibs ${CoreExtraLibs} ${CMAKE_DL_LIBS}) endif() @@ -1101,6 +1116,41 @@ set(NativeAssets assets/ppge_atlas.zim) set(LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT} ${nativeExtraLibs}) +if(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) + message(WARNING "FFMPEG_BUILDDIR variable is required to enable FFmpeg. Disabling it.") + unset(USE_FFMPEG) +endif(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR) + +if(USE_FFMPEG) + include_directories(ffmpeg ${FFMPEG_BUILDDIR}) + + add_library(libavformat STATIC IMPORTED) + set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavformat/libavformat.a) + add_library(libavcodec STATIC IMPORTED) + set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavcodec/libavcodec.a) + add_library(libavutil STATIC IMPORTED) + set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavutil/libavutil.a) + add_library(libswresample STATIC IMPORTED) + set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswresample/libswresample.a) + add_library(libswscale STATIC IMPORTED) + set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswscale/libswscale.a) + + SET (FFMPEG_LIBRARIES + libavcodec + libavformat + libavutil + libswresample + libswscale + ) + + if(APPLE) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} bz2 "-framework VideoDecodeAcceleration" "-framework CoreVideo") + endif(APPLE) + + set(LinkCommon ${LinkCommon} ${FFMPEG_LIBRARIES}) + add_definitions(-DUSE_FFMPEG) +endif(USE_FFMPEG) + if (TargetBin) if (IOS) add_executable(${TargetBin} MACOSX_BUNDLE ${NativeAppSource}) diff --git a/Core/Config.cpp b/Core/Config.cpp index 18c4c9504f..146f20e29f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -87,7 +87,7 @@ void Config::Load(const char *iniFileName) cpu->Get("FastMemory", &bFastMemory, false); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); - graphics->Get("ShowFPSCounter", &bShowFPSCounter, false); + graphics->Get("ShowFPSCounter", &iShowFPSCounter, false); graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false); #ifdef _WIN32 graphics->Get("ResolutionScale", &iWindowZoom, 2); @@ -109,7 +109,7 @@ void Config::Load(const char *iniFileName) #endif graphics->Get("VertexCache", &bVertexCache, true); graphics->Get("FullScreen", &bFullScreen, false); -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY graphics->Get("PartialStretch", &bPartialStretch, pixel_xres == pixel_yres); #endif graphics->Get("StretchToDisplay", &bStretchToDisplay, false); @@ -126,7 +126,7 @@ void Config::Load(const char *iniFileName) IniFile::Section *control = iniFile.GetOrCreateSection("Control"); control->Get("ShowStick", &bShowAnalogStick, false); -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY control->Get("ShowTouchControls", &bShowTouchControls, pixel_xres != pixel_yres); #elif defined(USING_GLES2) control->Get("ShowTouchControls", &bShowTouchControls, true); @@ -144,11 +144,11 @@ void Config::Load(const char *iniFileName) IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Get("NickName", &sNickName, "shadow"); pspConfig->Get("Language", &ilanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH); - pspConfig->Get("TimeFormat", &itimeformat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); + pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR); pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD); pspConfig->Get("TimeZone", &iTimeZone, 0); pspConfig->Get("DayLightSavings", &bDayLightSavings, PSP_SYSTEMPARAM_DAYLIGHTSAVINGS_STD); - pspConfig->Get("ButtonPreference", &bButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS); + pspConfig->Get("ButtonPreference", &iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS); pspConfig->Get("LockParentalLevel", &iLockParentalLevel, 0); pspConfig->Get("WlanAdhocChannel", &iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC); pspConfig->Get("WlanPowerSave", &bWlanPowerSave, PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF); @@ -197,7 +197,7 @@ void Config::Save() cpu->Set("FastMemory", bFastMemory); IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics"); - graphics->Set("ShowFPSCounter", bShowFPSCounter); + graphics->Set("ShowFPSCounter", iShowFPSCounter); graphics->Set("DisplayFramebuffer", bDisplayFramebuffer); graphics->Set("ResolutionScale", iWindowZoom); graphics->Set("BufferedRendering", bBufferedRendering); @@ -211,7 +211,7 @@ void Config::Save() graphics->Set("AnisotropyLevel", iAnisotropyLevel); graphics->Set("VertexCache", bVertexCache); graphics->Set("FullScreen", bFullScreen); -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY graphics->Set("PartialStretch", bPartialStretch); #endif graphics->Set("StretchToDisplay", bStretchToDisplay); @@ -240,11 +240,11 @@ void Config::Save() IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam"); pspConfig->Set("NickName", sNickName.c_str()); pspConfig->Set("Language", ilanguage); - pspConfig->Set("TimeFormat", itimeformat); + pspConfig->Set("TimeFormat", iTimeFormat); pspConfig->Set("DateFormat", iDateFormat); pspConfig->Set("TimeZone", iTimeZone); pspConfig->Set("DayLightSavings", bDayLightSavings); - pspConfig->Set("ButtonPreference", bButtonPreference); + pspConfig->Set("ButtonPreference", iButtonPreference); pspConfig->Set("LockParentalLevel", iLockParentalLevel); pspConfig->Set("WlanAdhocChannel", iWlanAdhocChannel); pspConfig->Set("WlanPowerSave", bWlanPowerSave); diff --git a/Core/Config.h b/Core/Config.h index c9bbc5d18d..9881c582bc 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -64,7 +64,7 @@ public: bool bNearestFiltering; bool bLinearFiltering; bool bUseVBO; -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY bool bPartialStretch; #endif bool bStretchToDisplay; @@ -96,7 +96,7 @@ public: bool bShowTouchControls; bool bShowDebuggerOnLoad; bool bShowAnalogStick; - bool bShowFPSCounter; + int iShowFPSCounter; bool bShowDebugStats; bool bLargeControls; bool bAccelerometerToAnalogHoriz; @@ -105,6 +105,7 @@ public: // 1 = arrow buttons // 2 = face buttons // 3 = L/R + // 4 = L/R + triangle/cross int iRightStickBind; // Control @@ -116,18 +117,18 @@ public: // SystemParam std::string sNickName; int ilanguage; - int itimeformat; + int iTimeFormat; int iDateFormat; int iTimeZone; bool bDayLightSavings; - bool bButtonPreference; + int iButtonPreference; int iLockParentalLevel; bool bEncryptSave; int iWlanAdhocChannel; bool bWlanPowerSave; std::string currentDirectory; - std::string externalDirectory; + std::string externalDirectory; std::string memCardDirectory; std::string flashDirectory; std::string internalDataDirectory; diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 2c0d93934f..ebc302f720 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -7,7 +7,7 @@ #include "MIPS/MIPS.h" #include "Core/Config.h" -const static std::string CHEATS_DIR = "Cheats"; +const static std::string CHEATS_DIR = "cheats"; static std::string activeCheatFile; static int CheatEvent = -1; diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 8191389202..70ea0362cc 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.50f; +const float FONT_SCALE = 0.55f; PSPMsgDialog::PSPMsgDialog() : PSPDialog() @@ -173,6 +173,7 @@ void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo) } } PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF)); + PPGeDrawTextWrapped(text.c_str(), 241.0f, y+3, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, 0x20000000); float sy = 122.0f - h2, ey = 150.0f + h2; PPGeDrawRect(15.0f, sy, 465.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF)); PPGeDrawRect(15.0f, ey, 465.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF)); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 823683b835..ea1c178ec7 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -21,6 +21,7 @@ #include "Core/Dialog/PSPOskDialog.h" #include "Core/Util/PPGeDraw.h" #include "Core/HLE/sceCtrl.h" +#include "Core/HLE/sceUtility.h" #include "Core/Config.h" #include "Core/Reporting.h" #include "Common/ChunkFile.h" @@ -750,7 +751,7 @@ int PSPOskDialog::Update() StartDraw(); PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0x63636363)); RenderKeyboard(); - if (g_Config.bButtonPreference) + if (g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE) { PPGeDrawImage(I_CROSS, 30, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF)); PPGeDrawImage(I_CIRCLE, 150, 220, 20, 20, 0, CalcFadedColor(0xFFFFFFFF)); @@ -795,7 +796,7 @@ int PSPOskDialog::Update() selectedChar = (selectedChar + (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard])) % (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard]); - if ((IsButtonPressed(CTRL_CROSS) && g_Config.bButtonPreference) || (IsButtonPressed(CTRL_CIRCLE) && !g_Config.bButtonPreference)) + if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CROSS : CTRL_CIRCLE)) { inputChars = CombinationString(true); } @@ -816,7 +817,7 @@ int PSPOskDialog::Update() selectedChar = selectedRow * numKeyCols[currentKeyboard] + selectedExtra; } - else if ((IsButtonPressed(CTRL_CIRCLE) && g_Config.bButtonPreference) || (IsButtonPressed(CTRL_CROSS) && !g_Config.bButtonPreference)) + else if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CROSS : CTRL_CIRCLE)) { if (inputChars.size() > 0) { diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 1c1a1b8023..175e2b9151 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -223,7 +223,6 @@ const std::string PSPSaveDialog::GetSelectedSaveDirName() return param.GetSaveDirName(param.GetPspParam()); // Intentional fallthrough when saveName not valid. - // TODO: Test these to see what they use for the filename. case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE: case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA: case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: @@ -233,7 +232,7 @@ const std::string PSPSaveDialog::GetSelectedSaveDirName() case SCE_UTILITY_SAVEDATA_TYPE_ERASESECURE: case SCE_UTILITY_SAVEDATA_TYPE_ERASE: case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA: - if (param.GetSaveDirName(param.GetPspParam(), currentSelectedSave) == "<>") + if (param.GetSaveName(param.GetPspParam()).length() != 0) return param.GetSaveDirName(param.GetPspParam()); // Intentional fallthrough when saveName not valid. @@ -356,14 +355,24 @@ void PSPSaveDialog::DisplaySaveDataInfo1() char hour_time[10] ; int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour; int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min; - if (g_Config.itimeformat == PSP_SYSTEMPARAM_TIME_FORMAT_12HR) { + switch (g_Config.iTimeFormat) { + case 1: if (hour > 12) { strcpy(am_pm, "PM"); hour -= 12; } snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); - } else - snprintf(hour_time,10,"%02d:%02d", hour, min); + break; + case 2: + snprintf(hour_time,10,"%02d:%02d", hour, min); + break; + default: + if (hour > 12) { + strcpy(am_pm, "PM"); + hour -= 12; + } + snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); + } snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title); int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday; @@ -371,14 +380,15 @@ void PSPSaveDialog::DisplaySaveDataInfo1() int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900; s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024; switch (g_Config.iDateFormat) { - case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: - snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK); + case 1: + snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); break; - case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY: + case 2: snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK); break; - case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: - // fall through + case 3: + snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK); + break; default: snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK); } @@ -408,14 +418,24 @@ void PSPSaveDialog::DisplaySaveDataInfo2() char hour_time[10] ; int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour; int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min; - if (g_Config.itimeformat == PSP_SYSTEMPARAM_TIME_FORMAT_12HR) { + switch (g_Config.iTimeFormat) { + case 1: if (hour > 12) { strcpy(am_pm, "PM"); hour -= 12; } snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); - } else - snprintf(hour_time,10,"%02d:%02d", hour, min); + break; + case 2: + snprintf(hour_time,10,"%02d:%02d", hour, min); + break; + default: + if (hour > 12) { + strcpy(am_pm, "PM"); + hour -= 12; + } + snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm); + } const char *saveTitle = param.GetFileInfo(currentSelectedSave).saveTitle; int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday; @@ -423,14 +443,14 @@ void PSPSaveDialog::DisplaySaveDataInfo2() int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900; s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024; switch (g_Config.iDateFormat) { - case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: - snprintf(date, 256, "%02d/%02d/%d", day, month, year); - break; - case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY: + case 1: + snprintf(date, 256, "%d/%02d/%02d", year, month, day); + case 2: snprintf(date, 256, "%02d/%02d/%d", month, day, year); break; - case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: - // fall through + case 3: + snprintf(date, 256, "%02d/%02d/%d", day, month, year); + break; default: snprintf(date, 256, "%d/%02d/%02d", year, month, day); } diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 02693a1e33..aee1205b1a 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -264,7 +264,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save cryptedSize = param->dataSize; if(cryptedSize == 0 || (SceSize)cryptedSize > param->dataBufSize) cryptedSize = param->dataBufSize; // fallback, should never use this - u8* data_ = (u8*)Memory::GetPointer(param->dataBuf); + u8 *data_ = param->dataBuf; int aligned_len = align16(cryptedSize); cryptedData = new u8[aligned_len + 0x10]; @@ -369,7 +369,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save if(param->dataBuf != 0) // Can launch save without save data in mode 13 { std::string filePath = dirPath+"/"+GetFileName(param); - u8* data_ = 0; + u8 *data_ = 0; SceSize saveSize = 0; if(cryptedData == 0) // Save decrypted data { @@ -377,7 +377,7 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save if(saveSize == 0 || saveSize > param->dataBufSize) saveSize = param->dataBufSize; // fallback, should never use this - data_ = (u8*)Memory::GetPointer(param->dataBuf); + data_ = param->dataBuf; } else { @@ -404,33 +404,29 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save // SAVE ICON0 - if (param->icon0FileData.buf) + if (param->icon0FileData.buf.Valid()) { - u8* data_ = (u8*)Memory::GetPointer(param->icon0FileData.buf); std::string icon0path = dirPath + "/" + ICON0_FILENAME; - WritePSPFile(icon0path, data_, param->icon0FileData.bufSize); + WritePSPFile(icon0path, param->icon0FileData.buf, param->icon0FileData.bufSize); } // SAVE ICON1 - if (param->icon1FileData.buf) + if (param->icon1FileData.buf.Valid()) { - u8* data_ = (u8*)Memory::GetPointer(param->icon1FileData.buf); std::string icon1path = dirPath + "/" + ICON1_FILENAME; - WritePSPFile(icon1path, data_, param->icon1FileData.bufSize); + WritePSPFile(icon1path, param->icon1FileData.buf, param->icon1FileData.bufSize); } // SAVE PIC1 - if (param->pic1FileData.buf) + if (param->pic1FileData.buf.Valid()) { - u8* data_ = (u8*)Memory::GetPointer(param->pic1FileData.buf); std::string pic1path = dirPath + "/" + PIC1_FILENAME; - WritePSPFile(pic1path, data_, param->pic1FileData.bufSize); + WritePSPFile(pic1path, param->pic1FileData.buf, param->pic1FileData.bufSize); } // Save SND - if (param->snd0FileData.buf) + if (param->snd0FileData.buf.Valid()) { - u8* data_ = (u8*)Memory::GetPointer(param->snd0FileData.buf); std::string snd0path = dirPath + "/" + SND0_FILENAME; - WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); + WritePSPFile(snd0path, param->snd0FileData.buf, param->snd0FileData.bufSize); } return true; @@ -442,7 +438,7 @@ bool SavedataParam::Load(SceUtilitySavedataParam *param, const std::string &save return false; } - u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf); + u8 *data_ = param->dataBuf; std::string dirPath = GetSaveFilePath(param, GetSaveDir(param, saveDirName)); if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it @@ -1040,14 +1036,13 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) listEmptyFile = false; } - typedef char (*SaveNameListData_t)[20]; - SaveNameListData_t saveNameListData; + SceUtilitySavedataSaveName *saveNameListData; bool hasMultipleFileName = false; - if (param->saveNameList != 0) + if (param->saveNameList.Valid()) { Clear(); - saveNameListData = (SaveNameListData_t)Memory::GetPointer(param->saveNameList); + saveNameListData = param->saveNameList; // Get number of fileName in array saveDataListCount = 0; @@ -1210,15 +1205,14 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName) saveInfo.idx = 0; saveInfo.textureData = 0; - if (Memory::IsValidAddress(GetPspParam()->newData)) + if (GetPspParam()->newData.Valid() && GetPspParam()->newData->buf.Valid()) { // We have a png to show if (!noSaveIcon) { noSaveIcon = new SaveFileInfo(); - PspUtilitySavedataFileData newData; - Memory::ReadStruct(GetPspParam()->newData, &newData); - CreatePNGIcon(Memory::GetPointer(newData.buf), (int)newData.size, *noSaveIcon); + PspUtilitySavedataFileData *newData = GetPspParam()->newData; + CreatePNGIcon(newData->buf, (int)newData->size, *noSaveIcon); } saveInfo.textureData = noSaveIcon->textureData; saveInfo.textureWidth = noSaveIcon->textureWidth; diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 979c43f533..6fa1ddc69c 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -77,7 +77,7 @@ struct PspUtilitySavedataSFOParam }; struct PspUtilitySavedataFileData { - int buf; + PSPPointer buf; SceSize bufSize; // Size of the buffer pointed to by buf SceSize size; // Actual file size to write / was read int unknown; @@ -128,6 +128,8 @@ struct SceUtilitySavedataFileListInfo PSPPointer systemEntries; }; +typedef char SceUtilitySavedataSaveName[20]; + // Structure to hold the parameters for the sceUtilitySavedataInitStart function. struct SceUtilitySavedataParam { @@ -142,14 +144,14 @@ struct SceUtilitySavedataParam char gameName[13]; char unused[3]; /** saveName: name of the particular save, normally a number */ - char saveName[20]; - u32 saveNameList; + SceUtilitySavedataSaveName saveName; + PSPPointer saveNameList; /** fileName: name of the data file of the game for example DATA.BIN */ char fileName[13]; char unused2[3]; /** pointer to a buffer that will contain data file unencrypted data */ - u32 dataBuf; // Initially void*, but void* in 64bit system take 8 bytes. + PSPPointer dataBuf; /** size of allocated space to dataBuf */ SceSize dataBufSize; SceSize dataSize; // Size of the actual save data @@ -161,7 +163,7 @@ struct SceUtilitySavedataParam PspUtilitySavedataFileData pic1FileData; PspUtilitySavedataFileData snd0FileData; - u32 newData; + PSPPointer newData; int focus; int abortStatus; diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index f26844e70d..61cc4593a3 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -212,7 +212,7 @@ bool MetaFileSystem::MapFilePath(const std::string &_inpath, std::string &outpat outpath = realpath.substr(prefLen); *system = &(fileSystems[i]); - DEBUG_LOG(HLE, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath.c_str()); + VERBOSE_LOG(HLE, "MapFilePath: mapped \"%s\" to prefix: \"%s\", path: \"%s\"", inpath.c_str(), fileSystems[i].prefix.c_str(), outpath.c_str()); return true; } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 3f3ea5175f..2795b80c25 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -528,7 +528,7 @@ u32 _AtracAddStreamData(int atracID, u8 *buf, u32 bytesToAdd) { // because that function would tell games how to add the left stream data. u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { - INFO_LOG(HLE, "sceAtracAddStreamData(%i, %08x)", atracID, bytesToAdd); + DEBUG_LOG(HLE, "sceAtracAddStreamData(%i, %08x)", atracID, bytesToAdd); Atrac *atrac = getAtrac(atracID); if (!atrac) { return 0; @@ -566,6 +566,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int } else { // TODO: This isn't at all right, but at least it makes the music "last" some time. u32 numSamples = 0; + u32 atracSamplesPerFrame = (atrac->codeType == PSP_MODE_AT_3_PLUS ? ATRAC3PLUS_MAX_SAMPLES : ATRAC3_MAX_SAMPLES); #ifdef USE_FFMPEG if (atrac->codeType == PSP_MODE_AT_3 && atrac->pCodecCtx) { int forceseekSample = atrac->currentSample * 2 > atrac->endSample ? 0 : atrac->endSample; @@ -580,7 +581,11 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int if (avret < 0) { ERROR_LOG(HLE, "avcodec_decode_audio4: Error decoding audio %d", avret); av_free_packet(&packet); - break; + // Avoid getting stuck in a loop (Virtua Tennis) + *SamplesNum = 0; + *finish = 1; + *remains = 0; + return ATRAC_ERROR_ALL_DATA_DECODED; } if (got_frame) { @@ -635,7 +640,6 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int } else { numSamples = atrac->endSample - atrac->currentSample; - 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) { @@ -654,7 +658,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample); int finishFlag = 0; - if (atrac->loopNum != 0 && (atrac->currentSample >= atrac->loopEndSample || + if (atrac->loopNum != 0 && (atrac->currentSample + atracSamplesPerFrame > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { atrac->currentSample = atrac->loopStartSample; if (atrac->loopNum > 0) diff --git a/Core/HLE/sceChnnlsv.cpp b/Core/HLE/sceChnnlsv.cpp index 27c583819e..25d96d613a 100644 --- a/Core/HLE/sceChnnlsv.cpp +++ b/Core/HLE/sceChnnlsv.cpp @@ -27,321 +27,217 @@ extern "C" u8 dataBuf[2048+20]; u8* dataBuf2 = dataBuf + 20; -static const u8 hash198C[16] = {0xFA, 0xAA, 0x50, 0xEC, 0x2F, 0xDE, 0x54, 0x93, 0xAD, 0x14, 0xB2, 0xCE, 0xA5, 0x30, 0x05, 0xDF }; -static const u8 hash19BC[16] = {0xCB, 0x15, 0xF4, 0x07, 0xF9, 0x6A, 0x52, 0x3C, 0x04, 0xB9, 0xB2, 0xEE, 0x5C, 0x53, 0xFA, 0x86 }; +static const u8 hash198C[16] = {0xFA, 0xAA, 0x50, 0xEC, 0x2F, 0xDE, 0x54, 0x93, 0xAD, 0x14, 0xB2, 0xCE, 0xA5, 0x30, 0x05, 0xDF}; +static const u8 hash19BC[16] = {0xCB, 0x15, 0xF4, 0x07, 0xF9, 0x6A, 0x52, 0x3C, 0x04, 0xB9, 0xB2, 0xEE, 0x5C, 0x53, 0xFA, 0x86}; -static const u8 key000019CC[16] = {0x70, 0x44, 0xA3, 0xAE, 0xEF, 0x5D, 0xA5, 0xF2, 0x85, 0x7F, 0xF2, 0xD6, 0x94, 0xF5, 0x36, 0x3B}; -static const u8 key000019DC[16] = {0xEC, 0x6D, 0x29, 0x59, 0x26, 0x35, 0xA5, 0x7F, 0x97, 0x2A, 0x0D, 0xBC, 0xA3, 0x26, 0x33, 0x00}; -static const u8 key0000199C[16] = {0x36, 0xA5, 0x3E, 0xAC, 0xC5, 0x26, 0x9E, 0xA3, 0x83, 0xD9, 0xEC, 0x25, 0x6C, 0x48, 0x48, 0x72}; -static const u8 key000019AC[16] = {0xD8, 0xC0, 0xB0, 0xF3, 0x3E, 0x6B, 0x76, 0x85, 0xFD, 0xFB, 0x4D, 0x7D, 0x45, 0x1E, 0x92, 0x03}; +static const u8 key19CC[16] = {0x70, 0x44, 0xA3, 0xAE, 0xEF, 0x5D, 0xA5, 0xF2, 0x85, 0x7F, 0xF2, 0xD6, 0x94, 0xF5, 0x36, 0x3B}; +static const u8 key19DC[16] = {0xEC, 0x6D, 0x29, 0x59, 0x26, 0x35, 0xA5, 0x7F, 0x97, 0x2A, 0x0D, 0xBC, 0xA3, 0x26, 0x33, 0x00}; +static const u8 key199C[16] = {0x36, 0xA5, 0x3E, 0xAC, 0xC5, 0x26, 0x9E, 0xA3, 0x83, 0xD9, 0xEC, 0x25, 0x6C, 0x48, 0x48, 0x72}; +static const u8 key19AC[16] = {0xD8, 0xC0, 0xB0, 0xF3, 0x3E, 0x6B, 0x76, 0x85, 0xFD, 0xFB, 0x4D, 0x7D, 0x45, 0x1E, 0x92, 0x03}; -int sub_000014BC(u8* data, int length) +void *memxor(void * dest, const void * src, size_t n) { - *(s32*)(data + 0) = 5; - *(s32*)(data + 12) = 256; - *(s32*)(data + 4) = 0; - *(s32*)(data + 8) = 0; - *(s32*)(data + 16) = length; - int res = sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, 8); - if (res == 0) - return 0; - return -258; + char const *s = (char const*)src; + char *d = (char*)dest; + + for (; n > 0; n--) + *d++ ^= *s++; + + return dest; } -int sub_00001418(u8* data, int length, int val2) +// The reason for the values from *FromMode calculations are not known. +int numFromMode(int mode) { - *(s32*)(data + 12) = val2; - *(s32*)(data + 0) = 5; - *(s32*)(data + 4) = 0; - *(s32*)(data + 8) = 0; - *(s32*)(data + 16) = length; - int res = sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, 7); - if (res == 0) - return 0; - return -257; -} - - -int sub_000015B0(u8* data, int alignedLen, u8* buf, int val) -{ - u8 sp0[16]; - - for(int i = 0; i < 16; i++) - { - sp0[i] = data[alignedLen+i+4]; - } - int res = sub_00001418(data, alignedLen, val); - if (res != 0) - { - return res; - } - - for(int i = 0; i < 16; i++) - { - data[i] = data[i] ^ buf[i]; - } - for(int i = 0; i < 16; i++) - { - buf[i] = sp0[i]; - } - return 0; -} - -int sub_00000000(u8* data_out, u8* data, int alignedLen, u8* data2, int& data3, int mode) -{ - for(int i = 0; i < 16; i++) - { - data_out[20+i] = data2[i]; - } - int valS4 = 100; - int res; - if (mode == 6) - { - valS4 = 100; - for(int i = 0; i < 16; i++) - { - data_out[20+i] = data_out[20+i] ^ key000019DC[i]; - } - res = sub_000014BC(data_out, 16); - for(int i = 0; i < 16; i++) - { - data_out[i] = data_out[i] ^ key000019CC[i]; - } - } - else if (mode == 4) - { - valS4 = 87; - for(int i = 0; i < 16; i++) - { - data_out[20+i] = data_out[20+i] ^ key000019AC[i]; - } - res = sub_000014BC(data_out, 16); - for(int i = 0; i < 16; i++) - { - data_out[i] = data_out[i] ^ key0000199C[i]; - } - } - else if (mode == 2) - { - res = sub_000014BC(data_out, 16); - valS4 = 83; - } - else if (mode == 1) - { - res = sub_00001418(data_out, 16, 4); - valS4 = 83; - } - else if (mode == 3) - { - valS4 = 87; - for(int i = 0; i < 16; i++) - { - data_out[i+20] = data_out[i+20] ^ key000019AC[i]; - } - res = sub_00001418(data_out, 16, 14); - for(int i = 0; i < 16; i++) - { - data_out[i] = data_out[i] ^ key0000199C[i]; - } - } - else - { - valS4 = 100; - for(int i = 0; i < 16; i++) - { - data_out[i + 20] = data_out[i + 20] ^ key000019DC[i]; - } - res = sub_00001418(data_out, 16, 18); - for(int i = 0; i < 16; i++) - { - data_out[i] = data_out[i] ^ key000019CC[i]; - } - } - - u8 sp16[16]; - if (res != 0) - { - return res; - } - for(int i = 0; i < 16; i++) - { - sp16[i] = data_out[i]; - } - u8 sp0[16]; - if (data3 == 1) - { - for(int i = 0; i < 16; i++) - { - sp0[i] = 0; - } - } - else - { - for(int i = 0; i < 12; i++) - { - sp0[i] = sp16[i]; - } - sp0[12] = (data3-1) & 0xFF ; - sp0[13] = ((data3-1) >> 8) & 0xFF; - sp0[14] = ((data3-1) >> 16) & 0xFF; - sp0[15] = ((data3-1) >> 24) & 0xFF; - } - - if ((u32)20 < (u32)alignedLen + 20) - { - for(int i = 20; i < alignedLen + 20; i += 16) - { - for(int j = 0; j < 12; j++) - { - data_out[i+j] = sp16[j]; - } - data_out[12+i] = data3; - data_out[13+i] = (data3 >> 8) & 0xFF; - data_out[14+i] = (data3 >> 16) & 0xFF; - data_out[15+i] = (data3 >> 24) & 0xFF; - data3++; - } - } - - res = sub_000015B0(data_out, alignedLen, sp0, valS4); - if (res != 0) - { - return res; - } - if (res >= alignedLen) - { - return 0; - } - for(int i = 0; i < alignedLen; i++) - { - data[i] = data[i] ^ data_out[i]; - } - - return 0; -} - -int sub_000013C8(u8* data, int size, int num) -{ - *(int*)(data+0) = 4; - *(int*)(data+4) = 0; - *(int*)(data+8) = 0; - *(int*)(data+12) = num; - *(int*)(data+16) = size; - size = size + 20; - - int res = sceUtilsBufferCopyWithRange(data,size,data,size,4); - if(res != 0) - { - return -257; - } - return 0; -} - -int sub_00001468(u8* data, int size) -{ - *(int*)(data+0) = 4; - *(int*)(data+12) = 256; - *(int*)(data+4) = 0; - *(int*)(data+8) = 0; - *(int*)(data+16) = size; - size = size + 20; - - int res = sceUtilsBufferCopyWithRange(data,size,data,size,5); - if(res != 0) - { - return -258; - } - return 0; -} - -int sub_00001510(u8* data, int size, u8* result , int num) -{ - for(int i = 0; i < 16; i++) - { - int v1 = data[i+20]; - v1 = v1 ^ result[i]; - data[i+20] = v1; - } - - int res = sub_000013C8(data, size, num); - if(res != 0) - { - return res; - } - - for(int i = 0; i < 16; i++) - { - result[i] = data[size + i + 4]; - } - return 0; -} - -int sub_000017A8(u8* data) - { - int res = sceUtilsBufferCopyWithRange(data, 20, 0, 0, 14); - if (res == 0) - return 0; - return -261; -} - -int sceSdGetLastIndex(u32 addressCtx,u32 addressHash, u32 addressKey) -{ - pspChnnlsvContext1 ctx; - Memory::ReadStruct(addressCtx,&ctx); - u8* in_hash; - u8* in_key; - in_hash = Memory::GetPointer(addressHash); - in_key = Memory::GetPointer(addressKey); - - int res = sceSdGetLastIndex_(ctx, in_hash, in_key); - - Memory::WriteStruct(addressCtx,&ctx); - return res; -} -int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key) -{ - if(ctx.keyLength >= 17) - { - return -1026; - } int num = 0; - switch(ctx.mode) + switch(mode) { - case 6: - num = 17; - break; - case 4: - num = 13; + case 1: + num = 3; break; case 2: num = 5; break; - case 1: - num = 3; - break; case 3: num = 12; break; + case 4: + num = 13; + break; + case 6: + num = 17; + break; default: num = 16; break; } + return num; +} +int numFromMode2(int mode) +{ + int num = 18; + if (mode == 1) + num = 4; + else if (mode == 3) + num = 14; + return num; +} - memset(dataBuf2,0,16); +int typeFromMode(int mode) +{ + return (mode == 1 || mode == 2) ? 83 : + ((mode == 3 || mode == 4) ? 87 : 100); +} - int res = sub_000013C8(dataBuf,16,num); - if(res != 0) - { +int kirkSendCmd(u8* data, int length, int num, bool encrypt) +{ + *(int*)(data+0) = encrypt ? KIRK_MODE_ENCRYPT_CBC : KIRK_MODE_DECRYPT_CBC; + *(int*)(data+4) = 0; + *(int*)(data+8) = 0; + *(int*)(data+12) = num; + *(int*)(data+16) = length; + + if (sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, encrypt ? KIRK_CMD_ENCRYPT_IV_0 : KIRK_CMD_DECRYPT_IV_0)) + return -257; + + return 0; +} + +int kirkSendFuseCmd(u8* data, int length, bool encrypt) +{ + *(int*)(data+0) = encrypt ? KIRK_MODE_ENCRYPT_CBC : KIRK_MODE_DECRYPT_CBC; + *(int*)(data+4) = 0; + *(int*)(data+8) = 0; + *(int*)(data+12) = 256; + *(int*)(data+16) = length; + + // Note: CMD 5 and 8 are not available, will always return -1 + if (sceUtilsBufferCopyWithRange(data, length + 20, data, length + 20, encrypt ? KIRK_CMD_ENCRYPT_IV_FUSE : KIRK_CMD_DECRYPT_IV_FUSE)) + return -258; + + return 0; +} + +int sub_15B0(u8* data, int alignedLen, u8* buf, int val) +{ + u8 sp0[16]; + memcpy(sp0, data+alignedLen+4, 16); + + int res = kirkSendCmd(data, alignedLen, val, false); + if (res) return res; + + memxor(data, buf, 16); + memcpy(buf, sp0, 16); + return 0; +} + +int sub_0000(u8* data_out, u8* data, int alignedLen, u8* data2, int& data3, int mode) +{ + memcpy(data_out+20, data2, 16); + // Mode 1:2 is 83, 3:4 is 87, 5:6 is 100 + int type = typeFromMode(mode); + int res; + + if (type == 87) + memxor(data_out+20, key19AC, 16); + else if (type == 100) + memxor(data_out+20, key19DC, 16); + + // Odd is Cmd, Even is FuseCmd + switch(mode) + { + case 2: case 4: case 6: res = kirkSendFuseCmd(data_out, 16, false); + break; + case 1: case 3: default:res = kirkSendCmd(data_out, 16, numFromMode2(mode), false); + break; } - u8 data1[16]; - u8 data2[16]; + if (type == 87) + memxor(data_out, key199C, 16); + else if (type == 100) + memxor(data_out, key19CC, 16); - memcpy(data1,dataBuf2,16); - int tmp1 = 0; - if((s8)data1[0] < 0) - tmp1 = 135; + if (res) + return res; + + u8 sp0[16], sp16[16]; + memcpy(sp16, data_out, 16); + if (data3 == 1) + { + memset(sp0, 0, 16); + } + else + { + memcpy(sp0, sp16, 12); + *(u32*)(sp0+12) = data3-1; + } + + if (alignedLen > 0) + { + for(int i = 20; i < alignedLen + 20; i += 16) + { + memcpy(data_out+i, sp16, 12); + *(u32*)(data_out+12+i) = data3; + data3++; + } + } + + res = sub_15B0(data_out, alignedLen, sp0, type); + if (res) + return res; + + if (alignedLen > 0) + memxor(data, data_out, alignedLen); + + return 0; +} + +int sub_1510(u8* data, int size, u8* result , int num) +{ + memxor(data+20, result, 16); + + int res = kirkSendCmd(data, size, num, true); + if(res) + return res; + + memcpy(result, data+size+4, 16); + return 0; +} + +int sub_17A8(u8* data) +{ + if (sceUtilsBufferCopyWithRange(data, 20, 0, 0, 14) == 0) + return 0; + return -261; +} + +int sceSdGetLastIndex(u32 addressCtx, u32 addressHash, u32 addressKey) +{ + pspChnnlsvContext1 ctx; + Memory::ReadStruct(addressCtx, &ctx); + int res = sceSdGetLastIndex_(ctx, Memory::GetPointer(addressHash), Memory::GetPointer(addressKey)); + Memory::WriteStruct(addressCtx, &ctx); + return res; +} + +int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key) +{ + if(ctx.keyLength >= 17) + return -1026; + + int num = numFromMode(ctx.mode); + + memset(dataBuf2, 0, 16); + + int res = kirkSendCmd(dataBuf, 16, num, true); + if(res) + return res; + + u8 data1[16], data2[16]; + + memcpy(data1, dataBuf2, 16); + int tmp1 = (data1[0] & 0x80) ? 135 : 0; for(int i = 0; i < 15; i++) { @@ -373,72 +269,37 @@ int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key) int oldKeyLength = ctx.keyLength; *(s8*)(ctx.key + ctx.keyLength) = -128; - if(oldKeyLength + 1 < 16) - { - for(int i = oldKeyLength + 1; i < 16; i++) - { - *(s8*)(ctx.key + i) = 0; - } - } + int i = oldKeyLength + 1; + if(i < 16) + memset(ctx.key + i, 0, 16 - i); } - for(int i = 0; i < 16; i++) - { - ctx.key[i] = ctx.key[i] ^ data1[i]; - } + memxor(ctx.key, data1, 16); + memcpy(dataBuf2, ctx.key, 16); + memcpy(data2, ctx.result, 16); - for(int i = 0; i < 16; i++) - { - dataBuf2[i] = ctx.key[i]; - } - - for(int i = 0; i < 16; i++) - { - data2[i] = ctx.result[i]; - } - int ret = sub_00001510(dataBuf,16,data2,num); - if(ret != 0) - { + int ret = sub_1510(dataBuf, 16, data2, num); + if(ret) return ret; - } - if((u32)(ctx.mode-3) < 2) - { - for(int i = 0; i < 16; i++) - { - data2[i] = data2[i] ^ hash198C[i]; - } - } - else if((u32)(ctx.mode-5) < 2) - { - for(int i = 0; i < 16; i++) - { - data2[i] = data2[i] ^ hash19BC[i]; - } - } + if(ctx.mode == 3 || ctx.mode == 4) + memxor(data2, hash198C, 16); + else if(ctx.mode == 5 || ctx.mode == 6) + memxor(data2, hash19BC, 16); int cond = ((ctx.mode ^ 0x2) < 1 || (ctx.mode ^ 0x4) < 1 || ctx.mode == 6); if(cond != 0) { - for(int i = 0; i < 16; i++) - { - dataBuf2[i] = data2[i]; - } - int ret = sub_00001468(dataBuf,16); - if(ret != 0) - { + memcpy(dataBuf2, data2, 16); + int ret = kirkSendFuseCmd(dataBuf, 16, true); + if(ret) return ret; - } - int res = sub_000013C8(dataBuf,16,num); - if(res != 0) - { - return res; - } - for(int i = 0; i < 16; i++) - { - data2[i] = dataBuf2[i]; - } + int res = kirkSendCmd(dataBuf, 16, num, true); + if(res) + return res; + + memcpy(data2, dataBuf2, 16); } if(in_key != 0) @@ -448,37 +309,16 @@ int sceSdGetLastIndex_(pspChnnlsvContext1& ctx, u8* in_hash, u8* in_key) data2[i] = in_key[i] ^ data2[i]; } - for(int i = 0; i < 16; i++) - { - dataBuf2[i] = data2[i]; - } + memcpy(dataBuf2, data2, 16); - int res = sub_000013C8(dataBuf,16,num); - if(res != 0) - { + int res = kirkSendCmd(dataBuf, 16, num, true); + if(res) return res; - } - for(int i = 0; i < 16; i++) - { - data2[i] = dataBuf2[i]; - } - } - for(int i = 0; i < 16; i++) - { - in_hash[i] = data2[i]; - } - for(int i = 0; i < 16; i++) - { - ctx.result[i] = 0; + memcpy(data2, dataBuf2, 16); } - - for(int i = 0; i < 16; i++) - { - ctx.key[i] = 0; - } - ctx.keyLength = 0; - ctx.mode = 0; + memcpy(in_hash, data2, 16); + sceSdSetIndex_(ctx, 0); return 0; } @@ -495,8 +335,8 @@ int sceSdSetIndex(u32 addressCtx, int value) int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value) { ctx.mode = value; - memset(ctx.result,0,16); - memset(ctx.key,0,16); + memset(ctx.result, 0, 16); + memset(ctx.key, 0, 16); ctx.keyLength = 0; return 0; } @@ -505,104 +345,52 @@ int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value) int sceSdRemoveValue(u32 addressCtx, u32 addressData, int length) { pspChnnlsvContext1 ctx; - Memory::ReadStruct(addressCtx,&ctx); - u8* data; - data = Memory::GetPointer(addressData); + Memory::ReadStruct(addressCtx, &ctx); + int res = sceSdRemoveValue_(ctx, Memory::GetPointer(addressData), length); + Memory::WriteStruct(addressCtx, &ctx); - int res = sceSdRemoveValue_(ctx, data, length); - - Memory::WriteStruct(addressCtx,&ctx); return res; } int sceSdRemoveValue_(pspChnnlsvContext1& ctx, u8* data, int length) { if(ctx.keyLength >= 17) - { return -1026; - } + if(ctx.keyLength + length < 17) { - if(length == 0) - { - return 0; - } - for(int i = 0; i < length; i++) - { - ctx.key[ctx.keyLength+i] = data[i]; - } + memcpy(ctx.key+ctx.keyLength, data, length); ctx.keyLength = ctx.keyLength + length; return 0; } - int mode = ctx.mode; - int num = 0; - switch(mode) - { - case 6: - num = 17; - break; - case 4: - num = 13; - break; - case 2: - num = 5; - break; - case 1: - num = 3; - break; - case 3: - num = 12; - break; - default: - num = 16; - break; - } + int num = numFromMode(ctx.mode); - memset(dataBuf2,0,2048); + memset(dataBuf2, 0, 2048); + memcpy(dataBuf2, ctx.key, ctx.keyLength); - if(ctx.keyLength > 0) - { - memcpy(dataBuf2,ctx.key,ctx.keyLength); - } int len = (ctx.keyLength + length) & 0xF; if(len == 0) len = 16; - int oldLength = ctx.keyLength; + int newSize = ctx.keyLength; ctx.keyLength = len; int diff = length - len; - if(len != 0) + memcpy(ctx.key, data+diff, len); + for(int i = 0; i < diff; i++) { - memcpy(ctx.key,data+diff,len); - } - - int newSize = oldLength; - if(diff != 0) - { - for(int i = 0; i < diff; i++) + if(newSize == 2048) { - if(newSize == 2048) - { - int res = sub_00001510(dataBuf,2048,ctx.result,num); - if(res != 0) - { - return res; - } - newSize = 0; - } - dataBuf2[newSize] = data[i]; - newSize++; + int res = sub_1510(dataBuf, 2048, ctx.result, num); + if(res) + return res; + newSize = 0; } + dataBuf2[newSize] = data[i]; + newSize++; } - if(newSize == 0) - { - return 0; - } - int res = sub_00001510(dataBuf,newSize,ctx.result, num); - if(res == 0) - { - return res; - } + if(newSize) + sub_1510(dataBuf, newSize, ctx.result, num); + // The RE code showed this always returning 0. I suspect it would want to return res instead. return 0; } @@ -626,116 +414,49 @@ int sceSdCreateList_(pspChnnlsvContext2& ctx2, int mode, int uknw, u8* data, u8* ctx2.unkn = 1; if (uknw == 2) { - for(int i = 0; i < 16; i++) - { - ctx2.unknown[i] = data[i]; - } - if (cryptkey == 0) - { - return 0; - } + memcpy(ctx2.cryptedData, data, 16); + if (cryptkey) + memxor(ctx2.cryptedData, cryptkey, 16); - for(int i = 0; i < 16; i++) - { - ctx2.unknown[i] = ctx2.unknown[i] ^ cryptkey[i]; - } return 0; } else if (uknw == 1) { u8 kirkHeader[37]; u8* kirkData = kirkHeader+20; - int res = sub_000017A8(kirkHeader); - if (res != 0) - { + int res = sub_17A8(kirkHeader); + if (res) return res; - } - for(int i = 15; i >= 0 ; i--) + + memcpy(kirkHeader+20, kirkHeader, 16); + memset(kirkHeader+32, 0, 4); + + int type = typeFromMode(mode); + if (type == 87) + memxor(kirkData, key199C, 16); + else if (type == 100) + memxor(kirkData, key19CC, 16); + + switch (mode) { - kirkHeader[i+20] = kirkHeader[i]; - } - for(int i = 0; i < 4; i++) - { - kirkHeader[i+32] = 0; + case 2: case 4: case 6: res = kirkSendFuseCmd(kirkHeader, 16, true); + break; + case 1: case 3: default:res = kirkSendCmd(kirkHeader, 16, numFromMode2(mode), true); + break; } - if (mode == 6) - { - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019CC[i]; - } - res = sub_00001468(kirkHeader, 16); - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019DC[i]; - } - } - else if (mode == 4) - { - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key0000199C[i]; - } - res = sub_00001468(kirkHeader, 16); - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019AC[i]; - } - } - else if (mode == 2) - { - res = sub_00001468(kirkHeader, 16); - } - else if (mode == 1) - { - res = sub_000013C8(kirkHeader, 16, 4); - } - else if (mode == 3) - { - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key0000199C[i]; - } - res = sub_000013C8(kirkHeader, 16, 14); - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019AC[i]; - } - } - else - { - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019CC[i]; - } - res = sub_000013C8(kirkHeader, 16, 18); - for(int i = 0; i < 16; i++) - { - kirkData[i] = kirkData[i] ^ key000019DC[i]; - } - } + if (type == 87) + memxor(kirkData, key19AC, 16); + else if (type == 100) + memxor(kirkData, key19DC, 16); - if (res != 0) - { + if (res) return res; - } - for(int i = 0; i < 16; i++) - { - ctx2.unknown[i] = kirkData[i]; - } - for(int i = 0; i < 16; i++) - { - data[i] = kirkData[i]; - } - if (cryptkey != 0) - { - for(int i = 0; i < 16; i++) - { - ctx2.unknown[i] = ctx2.unknown[i] ^ cryptkey[i]; - } - } + memcpy(ctx2.cryptedData, kirkData, 16); + memcpy(data, kirkData, 16); + if (cryptkey) + memxor(ctx2.cryptedData, cryptkey, 16); } return 0; @@ -770,12 +491,10 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen) { for(i = 0; alignedLen >= 2048; i += 2048) { - int res = sub_00000000(kirkData, data + i, 2048, ctx.unknown, ctx.unkn, ctx.mode); - alignedLen = alignedLen - 2048; - if (res != 0) - { + int res = sub_0000(kirkData, data + i, 2048, ctx.cryptedData, ctx.unkn, ctx.mode); + alignedLen -= 2048; + if (res) return res; - } } } if (alignedLen == 0) @@ -783,8 +502,7 @@ int sceSdSetMember_(pspChnnlsvContext2& ctx, u8* data, int alignedLen) return 0; } - int res = sub_00000000(kirkData, data + i, alignedLen, ctx.unknown, ctx.unkn, ctx.mode); - return res; + return sub_0000(kirkData, data + i, alignedLen, ctx.cryptedData, ctx.unkn, ctx.mode); } int sceChnnlsv_21BE78B4(u32 ctxAddr) @@ -800,10 +518,7 @@ int sceChnnlsv_21BE78B4(u32 ctxAddr) int sceChnnlsv_21BE78B4_(pspChnnlsvContext2& ctx) { - for(int i = 0; i < 16; i++) - { - ctx.unknown[i] = 0; - } + memset(ctx.cryptedData, 0, 16); ctx.unkn = 0; ctx.mode = 0; @@ -822,6 +537,6 @@ const HLEFunction sceChnnlsv[] = void Register_sceChnnlsv() { - RegisterModule("sceChnnlsv",ARRAY_SIZE(sceChnnlsv),sceChnnlsv); + RegisterModule("sceChnnlsv", ARRAY_SIZE(sceChnnlsv), sceChnnlsv); kirk_init(); } diff --git a/Core/HLE/sceChnnlsv.h b/Core/HLE/sceChnnlsv.h index d6ec1480f3..df7604735f 100644 --- a/Core/HLE/sceChnnlsv.h +++ b/Core/HLE/sceChnnlsv.h @@ -23,7 +23,7 @@ typedef struct _pspChnnlsvContext1 { /** Context data */ u8 result[0x10]; - u8 key[0x10]; + u8 key[0x10]; int keyLength; } pspChnnlsvContext1; @@ -31,7 +31,7 @@ typedef struct _pspChnnlsvContext2 { /** Context data */ int mode; int unkn; - u8 unknown[0x92]; + u8 cryptedData[0x92]; } pspChnnlsvContext2; int sceSdSetIndex_(pspChnnlsvContext1& ctx, int value); diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index d38bd48151..7f828cb904 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -161,11 +161,11 @@ void __CtrlSetAnalog(float x, float y, int stick) { std::lock_guard guard(ctrlMutex); if (stick == 0) { - ctrlCurrent.analog[0] = (u8)(x * 127.f + 128.f); - ctrlCurrent.analog[1] = (u8)(-y * 127.f + 128.f); + ctrlCurrent.analog[0] = (u8)ceilf(x * 127.5f + 127.5f); + ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f); } else { - ctrlCurrent.analogRight[0] = (u8)(x * 127.f + 128.f); - ctrlCurrent.analogRight[1] = (u8)(-y * 127.f + 128.f); + ctrlCurrent.analogRight[0] = (u8)ceilf(x * 127.5f + 127.5f); + ctrlCurrent.analogRight[1] = (u8)ceilf(-y * 127.5f + 127.5f); } } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 7f7688deff..6a0fbe358e 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -426,7 +426,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { gpuStats.numFrames++; - if (g_Config.bShowFPSCounter) { + if (g_Config.iShowFPSCounter) { CalculateFPS(); } diff --git a/Core/HLE/sceHttp.cpp b/Core/HLE/sceHttp.cpp index 0ba77a7ec7..d755e2f5d2 100644 --- a/Core/HLE/sceHttp.cpp +++ b/Core/HLE/sceHttp.cpp @@ -25,14 +25,24 @@ int sceHttpSetResolveRetry(int connectionID, int retryCount) return 0; } +int sceHttpInit() { + ERROR_LOG(HLE, "UNIMPL sceHttpInit()"); + return 0; +} + +int sceHttpEnd() { + ERROR_LOG(HLE, "UNIMPL sceHttpInit()"); + return 0; +} + /* * 0x62411801 sceSircsInit 0x19155a2f sceSircsEnd 0x71eef62d sceSircsSend */ const HLEFunction sceHttp[] = { - {0xab1abe07,0,"sceHttpInit"}, - {0xd1c8945e,0,"sceHttpEnd"}, + {0xab1abe07,WrapI_V,"sceHttpInit"}, + {0xd1c8945e,WrapI_V,"sceHttpEnd"}, {0xa6800c34,0,"sceHttpInitCache"}, {0x78b54c09,0,"sceHttpEndCache"}, {0x59e6d16f,0,"sceHttpEnableCache"}, diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index ca073eca13..5d12ea8bcf 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -37,7 +37,7 @@ static u32 backlightOffTime; void __ImposeInit() { language = g_Config.ilanguage; - buttonValue = g_Config.bButtonPreference?PSP_SYSTEMPARAM_BUTTON_CROSS:PSP_SYSTEMPARAM_BUTTON_CIRCLE; + buttonValue = g_Config.iButtonPreference; umdPopup = PSP_UMD_POPUP_DISABLE; backlightOffTime = 0; } diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index d18392ae43..c5eb655449 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -292,10 +292,19 @@ void __KernelModuleShutdown() void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type) { - static u32 lastHI16RelocAddress = 0; + // Sometimes there are multiple LO16's or HI16's per pair, even though the ABI says nothing of this. + // For multiple LO16's, we need the original (unrelocated) instruction data of the HI16. + // For multiple HI16's, we just need to set each one. + struct HI16RelocInfo + { + u32 addr; + u32 data; + }; + + // We have to post-process the HI16 part, since it might be +1 or not depending on the LO16 value. static u32 lastHI16ExportAddress = 0; - static bool lastHI16Processed = false; - static u32 lastHILO16Address = 0; + static std::vector lastHI16Relocs; + static bool lastHI16Processed = true; u32 relocData = Memory::Read_Instruction(relocAddress); @@ -320,42 +329,52 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type) */ case R_MIPS_HI16: - if (!lastHI16Processed) - WARN_LOG_REPORT(LOADER, "Unsafe unpaired HI16 variable relocation @ %08x / %08x", lastHI16RelocAddress, relocAddress); + if (lastHI16ExportAddress != exportAddress) + { + if (!lastHI16Processed && lastHI16Relocs.size() >= 1) + WARN_LOG_REPORT(LOADER, "Unsafe unpaired HI16 variable relocation @ %08x / %08x", lastHI16Relocs[lastHI16Relocs.size() - 1].addr, relocAddress); + + lastHI16ExportAddress = exportAddress; + lastHI16Relocs.clear(); + } // After this will be an R_MIPS_LO16. If that addition overflows, we need to account for it in HI16. // The R_MIPS_LO16 and R_MIPS_HI16 will often be *different* relocAddress values. - lastHI16RelocAddress = relocAddress; - lastHI16ExportAddress = exportAddress; + HI16RelocInfo reloc; + reloc.addr = relocAddress; + reloc.data = Memory::Read_Instruction(relocAddress); + lastHI16Relocs.push_back(reloc); lastHI16Processed = false; break; case R_MIPS_LO16: { - // The ABI requires that these come in pairs. - if (lastHI16ExportAddress != exportAddress) - { - ERROR_LOG_REPORT(LOADER, "HI16 and LO16 imports do not match for %08x => %08x/%08x (hi16 export: %08x)", exportAddress, lastHI16RelocAddress, relocAddress, lastHI16ExportAddress); - break; - } - u32 relocDataHi = Memory::Read_Instruction(lastHI16RelocAddress); // Sign extend the existing low value (e.g. from addiu.) - u32 full = (relocDataHi << 16) + (s16)(u16)(relocData & 0xFFFF) + exportAddress; + const u32 exportOffsetLo = exportAddress + (s16)(u16)(relocData & 0xFFFF); + u32 full = exportOffsetLo; - if (!lastHI16Processed) + // The ABI requires that these come in pairs, at least. + if (lastHI16Relocs.empty()) + ERROR_LOG_REPORT(LOADER, "LO16 without any HI16 variable import at %08x for %08x", relocAddress, exportAddress) + // Try to process at least the low relocation... + else if (lastHI16ExportAddress != exportAddress) + ERROR_LOG_REPORT(LOADER, "HI16 and LO16 imports do not match at %08x for %08x (should be %08x)", relocAddress, lastHI16ExportAddress, exportAddress) + else { - // The low instruction will be a signed add, which means (full & 0x8000) will subtract. - // We add 1 in that case so that it ends up the right value. - u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0); - Memory::Write_U32((relocDataHi & ~0xFFFF) | high, lastHI16RelocAddress); + // Process each of the HI16. Usually there's only one. + for (auto it = lastHI16Relocs.begin(), end = lastHI16Relocs.end(); it != end; ++it) + { + full = (it->data << 16) + exportOffsetLo; + // The low instruction will be a signed add, which means (full & 0x8000) will subtract. + // We add 1 in that case so that it ends up the right value. + u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0); + Memory::Write_U32((it->data & ~0xFFFF) | high, it->addr); + } lastHI16Processed = true; } - else if (lastHILO16Address != full) - WARN_LOG_REPORT(LOADER, "Potentially unsafe unpaired LO16 variable relocation @ %08x / %08x", lastHI16RelocAddress, relocAddress); - // And then this is the low relocation, hurray. + // With full set above (hopefully), now we just need to correct the low instruction. relocData = (relocData & ~0xFFFF) | (full & 0xFFFF); - lastHILO16Address = full; } break; diff --git a/Core/HLE/sceMp3.cpp b/Core/HLE/sceMp3.cpp index 53a4392c2e..60377e0ea2 100644 --- a/Core/HLE/sceMp3.cpp +++ b/Core/HLE/sceMp3.cpp @@ -17,31 +17,41 @@ #include #include "Core/HLE/HLE.h" +#include "Core/HLE/sceMp3.h" #include "Core/HW/MediaEngine.h" #include "Core/Reporting.h" +#include "../HW/MediaEngine.h" + +#ifdef USE_FFMPEG +#ifndef PRId64 +#define PRId64 "%llu" +#endif + +// Urgh! Why is this needed? +#ifdef ANDROID +#ifndef UINT64_C +#define UINT64_C(c) (c ## ULL) +#endif +#endif +extern "C" { +#include +#include +//#include // iOS build is not happy with this one. +#include +#include +} +#endif static const int MP3_BITRATES[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}; -struct Mp3Context { - Mp3Context() : mediaengine(NULL) {} - ~Mp3Context() { - if (mediaengine != NULL) { - delete mediaengine; - } - } - +struct Mp3Context { void DoState(PointerWrap &p) { p.Do(mp3StreamStart); p.Do(mp3StreamEnd); p.Do(mp3Buf); p.Do(mp3BufSize); p.Do(mp3PcmBuf); - p.Do(mp3BufPendingSize); p.Do(mp3PcmBufSize); - p.Do(mp3InputFileReadPos); - p.Do(mp3InputBufWritePos); - p.Do(mp3InputBufSize); - p.Do(mp3InputFileSize); p.Do(mp3DecodedBytes); p.Do(mp3LoopNum); p.Do(mp3MaxSamples); @@ -53,32 +63,37 @@ struct Mp3Context { p.DoMarker("Mp3Context"); } - u64 mp3StreamStart; - u64 mp3StreamEnd; - u64 mp3StreamPosition; + int mp3StreamStart; + int mp3StreamEnd; u32 mp3Buf; int mp3BufSize; - int mp3BufPendingSize; u32 mp3PcmBuf; int mp3PcmBufSize; - int mp3InputFileReadPos; - int mp3InputBufWritePos; - int mp3InputBufSize; - int mp3InputFileSize; + int readPosition; + + int bufferRead; + int bufferWrite; + int bufferAvailable; + int mp3DecodedBytes; int mp3LoopNum; int mp3MaxSamples; + MediaEngine *mediaengine; int mp3Channels; int mp3Bitrate; int mp3SamplingRate; int mp3Version; - - MediaEngine *mediaengine; +#ifdef USE_FFMPEG + AVFormatContext *avformat_context; + AVIOContext *avio_context; + AVCodecContext *decoder_context; + SwrContext *resampler_context; + int audio_stream_index; +#endif }; - static std::map mp3Map; static u32 lastMp3Handle = 0; @@ -87,11 +102,13 @@ Mp3Context *getMp3Ctx(u32 mp3) { ERROR_LOG(HLE, "Bad mp3 handle %08x - using last one (%08x) instead", mp3, lastMp3Handle); mp3 = lastMp3Handle; } + if (mp3Map.find(mp3) == mp3Map.end()) return NULL; return mp3Map[mp3]; } +/* MP3 */ int sceMp3Decode(u32 mp3, u32 outPcmPtr) { DEBUG_LOG(HLE, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr); @@ -102,43 +119,90 @@ int sceMp3Decode(u32 mp3, u32 outPcmPtr) { } // Nothing to decode - if(ctx->mp3BufPendingSize == 0 || ctx->mp3StreamPosition >= ctx->mp3StreamEnd) { - if (ctx->mp3LoopNum == 0) { - return 0; - } else if (ctx->mp3LoopNum > 0) { - --ctx->mp3LoopNum; - } + if (ctx->bufferAvailable == 0 || ctx->readPosition >= ctx->mp3StreamEnd) { + return 0; } + int bytesdecoded = 0; +#ifndef USE_FFMPEG Memory::Memset(ctx->mp3PcmBuf, 0, ctx->mp3PcmBufSize); Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); +#else - // TODO: Actually decode the data -#ifdef _DEBUG + AVFrame frame; + memset(&frame, 0, sizeof(frame)); + AVPacket packet; + memset(&packet, 0, sizeof(packet)); + int got_frame = 0, ret; + static int audio_frame_count = 0; + + while (!got_frame) { + if ((ret = av_read_frame(ctx->avformat_context, &packet)) < 0) + break; + + if (packet.stream_index == ctx->audio_stream_index) { + avcodec_get_frame_defaults(&frame); + got_frame = 0; + ret = avcodec_decode_audio4(ctx->decoder_context, &frame, &got_frame, &packet); + if (ret < 0) { + ERROR_LOG(HLE, "avcodec_decode_audio4: Error decoding audio %d", ret); + continue; + } + if (got_frame) { + //char buf[1024] = ""; + //av_ts_make_time_string(buf, frame.pts, &ctx->decoder_context->time_base); + //DEBUG_LOG(HLE, "audio_frame n:%d nb_samples:%d pts:%s", audio_frame_count++, frame.nb_samples, buf); + + /* + u8 *audio_dst_data; + int audio_dst_linesize; + + ret = av_samples_alloc(&audio_dst_data, &audio_dst_linesize, frame.channels, frame.nb_samples, (AVSampleFormat)frame.format, 1); + if (ret < 0) { + ERROR_LOG(HLE, "av_samples_alloc: Could not allocate audio buffer %d", ret); + return -1; + } + */ + + int decoded = av_samples_get_buffer_size(NULL, frame.channels, frame.nb_samples, (AVSampleFormat)frame.format, 1); + + u8* out = Memory::GetPointer(ctx->mp3PcmBuf + bytesdecoded); + ret = swr_convert(ctx->resampler_context, &out, frame.nb_samples, (const u8**)frame.extended_data, frame.nb_samples); + if (ret < 0) { + ERROR_LOG(HLE, "swr_convert: Error while converting %d", ret); + return -1; + } + + //av_samples_copy(&audio_dst_data, frame.data, 0, 0, frame.nb_samples, frame.channels, (AVSampleFormat)frame.format); + + //memcpy(Memory::GetPointer(ctx->mp3PcmBuf + bytesdecoded), audio_dst_data, decoded); + bytesdecoded += decoded; + // av_freep(&audio_dst_data[0]); + } + } + av_free_packet(&packet); + } + Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); +#endif + + #if 0 && defined(_DEBUG) char fileName[256]; - sprintf(fileName, "%lli.mp3", ctx->mp3StreamPosition); + sprintf(fileName, "out.wav", mp3); - FILE * file = fopen(fileName, "wb"); - if(file) { - if(!Memory::IsValidAddress(ctx->mp3Buf)) { + FILE * file = fopen(fileName, "a+b"); + if (file) { + if (!Memory::IsValidAddress(ctx->mp3Buf)) { ERROR_LOG(HLE, "sceMp3Decode mp3Buf %08X is not a valid address!", ctx->mp3Buf); } - u8 * ptr = Memory::GetPointer(ctx->mp3Buf); - fwrite(ptr, 1, ctx->mp3BufPendingSize, file); - + //u8 * ptr = Memory::GetPointer(ctx->mp3Buf); + fwrite(Memory::GetPointer(ctx->mp3PcmBuf), 1, bytesdecoded, file); + fclose(file); } -#endif + #endif - ctx->mp3StreamPosition += ctx->mp3BufPendingSize; - if(ctx->mp3StreamPosition > ctx->mp3StreamEnd) - ctx->mp3StreamPosition = ctx->mp3StreamEnd; - - // Reset the pending buffer size so the program will know that we need to buffer more data - ctx->mp3BufPendingSize = (ctx->mp3StreamPosition < ctx->mp3StreamEnd)?-1:0; - - return ctx->mp3PcmBufSize; + return bytesdecoded; } int sceMp3ResetPlayPosition(u32 mp3) { @@ -149,8 +213,8 @@ int sceMp3ResetPlayPosition(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } - ctx->mp3StreamPosition = 0; - ctx->mp3BufPendingSize = -1; + + ctx->readPosition = ctx->mp3StreamStart; return 0; } @@ -162,7 +226,52 @@ int sceMp3CheckStreamDataNeeded(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } - return (ctx->mp3BufPendingSize < 0) && (ctx->mp3StreamPosition < ctx->mp3StreamEnd); + + return ctx->bufferAvailable != ctx->mp3BufSize && ctx->readPosition < ctx->mp3StreamEnd; +} + +int readFunc(void *opaque, uint8_t *buf, int buf_size) { + Mp3Context *ctx = static_cast(opaque); + + int res = 0; + while (ctx->bufferAvailable && buf_size) { + // Maximum bytes we can read + int to_read = std::min(ctx->bufferAvailable, buf_size); + + // Don't read past the end if the buffer loops + to_read = std::min(ctx->mp3BufSize - ctx->bufferRead, to_read); + memcpy(buf + res, Memory::GetCharPointer(ctx->mp3Buf + ctx->bufferRead), to_read); + + ctx->bufferRead += to_read; + if (ctx->bufferRead == ctx->mp3BufSize) + ctx->bufferRead = 0; + ctx->bufferAvailable -= to_read; + buf_size -= to_read; + res += to_read; + } + + if (ctx->bufferAvailable == 0) { + ctx->bufferRead = 0; + ctx->bufferWrite = 0; + } + +#if 0 && defined(_DEBUG) + char fileName[256]; + sprintf(fileName, "out.mp3"); + + FILE * file = fopen(fileName, "a+b"); + if (file) { + if (!Memory::IsValidAddress(ctx->mp3Buf)) { + ERROR_LOG(HLE, "sceMp3Decode mp3Buf %08X is not a valid address!", ctx->mp3Buf); + } + + fwrite(buf, 1, res, file); + + fclose(file); + } +#endif + + return res; } u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { @@ -178,13 +287,17 @@ u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { ctx->mp3PcmBuf = Memory::Read_U32(mp3Addr+24); ctx->mp3PcmBufSize = Memory::Read_U32(mp3Addr+28); - ctx->mp3StreamPosition = ctx->mp3StreamStart; - ctx->mp3BufPendingSize = -1; + ctx->readPosition = ctx->mp3StreamStart; ctx->mp3MaxSamples = ctx->mp3PcmBufSize / 4 ; - /*ctx->mp3Channels = 2; + ctx->mp3Channels = 2; ctx->mp3Bitrate = 128; - ctx->mp3SamplingRate = 44100;*/ + ctx->mp3SamplingRate = 44100; + +#ifdef USE_FFMPEG + ctx->avformat_context = NULL; + ctx->avio_context = NULL; +#endif mp3Map[mp3Addr] = ctx; return mp3Addr; @@ -214,36 +327,74 @@ int sceMp3Init(u32 mp3) { // 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); + ((header<<8) & 0x00FF0000) | + ((header>>8) & 0x0000FF00) | + (header << 24); - int channels = ((header >> 6) & 0x3); - if(channels == 0 || channels == 1 || channels == 2) - ctx->mp3Channels = 2; - else if(channels == 3) - ctx->mp3Channels = 1; - else - ctx->mp3Channels = 0; - - // 0 == VBR - int bitrate = ((header >> 10) & 0x3); - if(bitrate < (int)ARRAY_SIZE(MP3_BITRATES)) - ctx->mp3Bitrate = MP3_BITRATES[bitrate]; - else - ctx->mp3Bitrate = -1; - - int samplerate = ((header >> 12) & 0x3); - if (samplerate == 0) - ctx->mp3SamplingRate = 44100; - else if (samplerate == 1) - ctx->mp3SamplingRate = 48000; - else if (samplerate == 2) - ctx->mp3SamplingRate = 32000; - else - ctx->mp3SamplingRate = 0; - ctx->mp3Version = ((header >> 19) & 0x3); + +#ifdef USE_FFMPEG + 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; + + int ret; + if ((ret = avformat_open_input(&ctx->avformat_context, NULL, av_find_input_format("mp3"), NULL)) < 0) { + ERROR_LOG(HLE, "avformat_open_input: Cannot open input %d", ret); + return -1; + } + + if ((ret = avformat_find_stream_info(ctx->avformat_context, NULL)) < 0) { + ERROR_LOG(HLE, "avformat_find_stream_info: Cannot find stream information %d", ret); + return -1; + } + + AVCodec *dec; + + /* select the audio stream */ + ret = av_find_best_stream(ctx->avformat_context, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0); + if (ret < 0) { + ERROR_LOG(HLE, "av_find_best_stream: Cannot find a audio stream in the input file %d", ret); + return -1; + } + ctx->audio_stream_index = ret; + ctx->decoder_context = ctx->avformat_context->streams[ctx->audio_stream_index]->codec; + + /* init the audio decoder */ + if ((ret = avcodec_open2(ctx->decoder_context, dec, NULL)) < 0) { + ERROR_LOG(HLE, "avcodec_open2: Cannot open audio decoder %d", ret); + return -1; + } + + ctx->resampler_context = swr_alloc_set_opts(NULL, + ctx->decoder_context->channel_layout, + AV_SAMPLE_FMT_S16, + ctx->decoder_context->sample_rate, + ctx->decoder_context->channel_layout, + ctx->decoder_context->sample_fmt, + 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; + + if (!ctx->resampler_context) { + ERROR_LOG(HLE, "Could not allocate resampler context %d", ret); + return -1; + } + + if ((ret = swr_init(ctx->resampler_context)) < 0) { + ERROR_LOG(HLE, "Failed to initialize the resampling context %d", ret); + return -1; + } + + av_dump_format(ctx->avformat_context, 0, "mp3", 0); +#endif + return 0; } @@ -254,48 +405,40 @@ int sceMp3GetLoopNum(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3LoopNum; } -int sceMp3GetMaxOutputSample(u32 mp3) { +int sceMp3GetMaxOutputSample(u32 mp3) +{ DEBUG_LOG(HLE, "sceMp3GetMaxOutputSample(%08x)", mp3); Mp3Context *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3MaxSamples; } -int sceMp3NotifyAddStreamData(u32 mp3, int size) { - DEBUG_LOG(HLE, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); - - Mp3Context *ctx = getMp3Ctx(mp3); - if (!ctx) { - ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); - return -1; - } - ctx->mp3BufPendingSize = size; - return 0; -} - int sceMp3GetSumDecodedSample(u32 mp3) { ERROR_LOG_REPORT(HLE, "UNIMPL sceMp3GetSumDecodedSample(%08X)", mp3); return 0; } int sceMp3SetLoopNum(u32 mp3, int loop) { - DEBUG_LOG(HLE, "sceMp3SetLoopNum(%08X, %i)", mp3, loop); + INFO_LOG(HLE, "sceMp3SetLoopNum(%08X, %i)", mp3, loop); Mp3Context *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + ctx->mp3LoopNum = loop; + return 0; } - int sceMp3GetMp3ChannelNum(u32 mp3) { DEBUG_LOG(HLE, "sceMp3GetMp3ChannelNum(%08X)", mp3); @@ -304,9 +447,9 @@ int sceMp3GetMp3ChannelNum(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3Channels; } - int sceMp3GetBitRate(u32 mp3) { DEBUG_LOG(HLE, "sceMp3GetBitRate(%08X)", mp3); @@ -315,9 +458,9 @@ int sceMp3GetBitRate(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3Bitrate; } - int sceMp3GetSamplingRate(u32 mp3) { DEBUG_LOG(HLE, "sceMp3GetSamplingRate(%08X)", mp3); @@ -326,23 +469,59 @@ int sceMp3GetSamplingRate(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3SamplingRate; } int sceMp3GetInfoToAddStreamData(u32 mp3, u32 dstPtr, u32 towritePtr, u32 srcposPtr) { - DEBUG_LOG(HLE, "HACK: sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); - + INFO_LOG(HLE, "sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X)", mp3, dstPtr, towritePtr, srcposPtr); + Mp3Context *ctx = getMp3Ctx(mp3); if (!ctx) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } - if(Memory::IsValidAddress(dstPtr)) - Memory::Write_U32(ctx->mp3Buf, dstPtr); - if(Memory::IsValidAddress(towritePtr)) - Memory::Write_U32(ctx->mp3BufSize, towritePtr); - if(Memory::IsValidAddress(srcposPtr)) - Memory::Write_U32((u32)ctx->mp3StreamPosition, srcposPtr); + + u32 buf, max_write; + if (ctx->readPosition < ctx->mp3StreamEnd) { + buf = ctx->mp3Buf + ctx->bufferWrite; + max_write = std::min(ctx->mp3BufSize - ctx->bufferWrite, ctx->mp3BufSize - ctx->bufferAvailable); + } else { + buf = 0; + max_write = 0; + } + + if (Memory::IsValidAddress(dstPtr)) + Memory::Write_U32(buf, dstPtr); + if (Memory::IsValidAddress(towritePtr)) + Memory::Write_U32(max_write, towritePtr); + if (Memory::IsValidAddress(srcposPtr)) + Memory::Write_U32(ctx->readPosition, srcposPtr); + + return 0; +} + +int sceMp3NotifyAddStreamData(u32 mp3, int size) { + INFO_LOG(HLE, "sceMp3NotifyAddStreamData(%08X, %i)", mp3, size); + + Mp3Context *ctx = getMp3Ctx(mp3); + if (!ctx) { + ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); + return -1; + } + + ctx->readPosition += size; + ctx->bufferAvailable += size; + ctx->bufferWrite += size; + + if (ctx->bufferWrite == ctx->mp3BufSize) + ctx->bufferWrite = 0; + + if (ctx->readPosition >= ctx->mp3StreamEnd && ctx->mp3LoopNum != 0) { + ctx->readPosition = ctx->mp3StreamStart; + if (ctx->mp3LoopNum > 0) + ctx->mp3LoopNum--; + } return 0; } @@ -354,8 +533,15 @@ int sceMp3ReleaseMp3Handle(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, 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; + return 0; } @@ -381,11 +567,11 @@ u32 sceMp3GetVersion(u32 mp3) { ERROR_LOG(HLE, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); return -1; } + return ctx->mp3Version; } -const HLEFunction sceMp3[] = -{ +const HLEFunction sceMp3[] = { {0x07EC321A,WrapU_U,"sceMp3ReserveMp3Handle"}, {0x0DB149F4,WrapI_UI,"sceMp3NotifyAddStreamData"}, {0x2A368661,WrapI_U,"sceMp3ResetPlayPosition"}, @@ -412,7 +598,6 @@ const HLEFunction sceMp3[] = {0xe3ee2c81,0,"sceMp3_E3EE2C81"}, }; -void Register_sceMp3() -{ +void Register_sceMp3() { RegisterModule("sceMp3", ARRAY_SIZE(sceMp3), sceMp3); } diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 1ccf65b1e9..0f9d1d7c7e 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -301,6 +301,11 @@ void __MpegInit() { isCurrentMpegAnalyzed = false; isMpegInit = false; actionPostPut = __KernelRegisterActionType(PostPutAction::Create); + +#ifdef USING_FFMPEG + avcodec_register_all(); + av_register_all(); +#endif } void __MpegDoState(PointerWrap &p) { @@ -327,10 +332,11 @@ void __MpegShutdown() { u32 sceMpegInit() { if (isMpegInit) { WARN_LOG(HLE, "sceMpegInit(): already initialized"); - return ERROR_MPEG_ALREADY_INIT; + // TODO: Need to properly hook module load/unload for this to work right. + //return ERROR_MPEG_ALREADY_INIT; + } else { + INFO_LOG(HLE, "sceMpegInit()"); } - - INFO_LOG(HLE, "sceMpegInit()"); isMpegInit = true; return hleDelayResult(0, "mpeg init", 750); } @@ -862,17 +868,23 @@ int sceMpegQueryAtracEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr) int sceMpegRingbufferAvailableSize(u32 ringbufferAddr) { - if (!Memory::IsValidAddress(ringbufferAddr)) { + PSPPointer ringbuffer; + ringbuffer = ringbufferAddr; + + if (!ringbuffer.Valid()) { ERROR_LOG(HLE, "sceMpegRingbufferAvailableSize(%08x) - bad address", ringbufferAddr); return -1; } - SceMpegRingBuffer ringbuffer; - Memory::ReadStruct(ringbufferAddr, &ringbuffer); - DEBUG_LOG(HLE, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer.packetsFree, ringbufferAddr); - MpegContext *ctx = getMpegCtx(ringbuffer.mpeg); - int result = std::min(ringbuffer.packetsFree, ctx->mediaengine->getRemainSize() / 2048); - return ringbuffer.packetsFree; + MpegContext *ctx = getMpegCtx(ringbuffer->mpeg); + if (!ctx) { + ERROR_LOG(HLE, "sceMpegRingbufferAvailableSize(%08x) - bad mpeg", ringbufferAddr); + return -1; + } + + hleEatCycles(2020); + DEBUG_LOG(HLE, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr); + return ringbuffer->packetsFree; } void PostPutAction::run(MipsCall &call) { @@ -1009,10 +1021,11 @@ u32 sceMpegFinish() if (!isMpegInit) { WARN_LOG(HLE, "sceMpegFinish(...): not initialized"); - return ERROR_MPEG_NOT_YET_INIT; + // TODO: Need to properly hook module load/unload for this to work right. + //return ERROR_MPEG_NOT_YET_INIT; + } else { + INFO_LOG(HLE, "sceMpegFinish(...)"); } - - INFO_LOG(HLE, "sceMpegFinish(...)"); isMpegInit = false; //__MpegFinish(); return hleDelayResult(0, "mpeg finish", 250); diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 2ecba10ec0..2e31cd71fe 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -24,12 +24,16 @@ #include "sceUtility.h" static bool netInited; +static bool netInetInited; static bool netAdhocInited; +static bool netApctlInited; static u32 adhocctlHandlerCount; +static u32 apctlHandlerCount; // TODO: Determine how many handlers we can actually have const u32 MAX_ADHOCCTL_HANDLERS = 32; +const u32 MAX_APCTL_HANDLERS = 32; enum { ERROR_NET_BUFFER_TOO_SMALL = 0x80400706, @@ -88,9 +92,18 @@ struct AdhocctlHandler { static std::map adhocctlHandlers; +struct ApctlHandler { + u32 entryPoint; + u32 argument; +}; + +static std::map apctlHandlers; + void __NetInit() { netInited = false; netAdhocInited = false; + netApctlInited = false; + netInetInited = false; memset(&netMallocStat, 0, sizeof(netMallocStat)); } @@ -100,22 +113,40 @@ void __NetShutdown() { void __UpdateAdhocctlHandlers(int flag, int error) { u32 args[3] = { 0, 0, 0 }; + args[0] = flag; + args[1] = error; for(std::map::iterator it = adhocctlHandlers.begin(); it != adhocctlHandlers.end(); ++it) { - args[0] = flag; - args[1] = error; args[2] = it->second.argument; __KernelDirectMipsCall(it->second.entryPoint, NULL, args, 3, true); } } +void __UpdateApctlHandlers(int oldState, int newState, int flag, int error) { + u32 args[5] = { 0, 0, 0, 0, 0 }; + args[0] = oldState; + args[1] = newState; + args[2] = flag; + args[3] = error; + + for(std::map::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) { + args[4] = it->second.argument; + + __KernelDirectMipsCall(it->second.entryPoint, NULL, args, 5, true); + } +} + // This feels like a dubious proposition, mostly... void __NetDoState(PointerWrap &p) { p.Do(netInited); + p.Do(netInetInited); p.Do(netAdhocInited); + p.Do(netApctlInited); p.Do(adhocctlHandlers); p.Do(adhocctlHandlerCount); + p.Do(apctlHandlers); + p.Do(apctlHandlerCount); p.Do(netMallocStat); p.DoMarker("net"); } @@ -274,7 +305,7 @@ int sceNetAdhocPdpCreate(const char *mac, u32 port, int bufferSize, u32 unknown) // TODO: Should we really write the struct if we're disconnected? int sceNetAdhocctlGetParameter(u32 paramAddr) { - ERROR_LOG(HLE, "UNTESTED %x=sceNetAdhocctlGetParameter(%x)", 0, paramAddr); + WARN_LOG(HLE, "UNTESTED sceNetAdhocctlGetParameter(%x)", paramAddr); struct SceNetAdhocctlParams params; params.channel = 0; for(int i = 0; i < 6; i++) @@ -331,7 +362,7 @@ int sceNetAdhocctlConnect(u32 ptrToGroupName) { // Write static data since we don't actually manage any memory for sceNet* yet. int sceNetGetMallocStat(u32 statPtr) { - ERROR_LOG(HLE, "UNTESTED sceNetGetMallocStat(%x)", statPtr); + WARN_LOG(HLE, "UNTESTED sceNetGetMallocStat(%x)", statPtr); if(Memory::IsValidAddress(statPtr)) Memory::WriteStruct(statPtr, &netMallocStat); else @@ -345,6 +376,88 @@ int sceNetAdhocMatchingInit(u32 memsize) { return 0; } +int sceNetInetInit() { + ERROR_LOG(HLE, "UNIMPL sceNetInetInit()"); + if (netInetInited) + return ERROR_NET_ADHOC_ALREADY_INITIALIZED; // TODO: What's the proper error for netInet already being inited? + netInetInited = true; + + return 0; +} + +int sceNetInetTerm() { + ERROR_LOG(HLE, "UNIMPL sceNetInetTerm()"); + netInetInited = false; + + return 0; +} + +int sceNetApctlInit() { + ERROR_LOG(HLE, "UNIMPL sceNetApctlInit()"); + if (netAdhocInited) + return ERROR_NET_ADHOC_ALREADY_INITIALIZED; // TODO: What's the proper error for apctl already being inited? + netApctlInited = true; + + return 0; +} + +int sceNetApctlTerm() { + ERROR_LOG(HLE, "UNIMPL sceNeApctlTerm()"); + netInetInited = false; + + return 0; +} + +// TODO: How many handlers can the PSP actually have for Apctl? +// TODO: Should we allow the same handler to be added more than once? +u32 sceNetApctlAddHandler(u32 handlerPtr, u32 handlerArg) { + bool foundHandler = false; + u32 retval = apctlHandlerCount; + struct ApctlHandler handler; + memset(&handler, 0, sizeof(handler)); + + handler.entryPoint = handlerPtr; + handler.argument = handlerArg; + + for(std::map::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); it++) { + if(it->second.entryPoint == handlerPtr) { + foundHandler = true; + break; + } + } + + if(!foundHandler && Memory::IsValidAddress(handlerPtr)) { + if(apctlHandlerCount >= MAX_APCTL_HANDLERS) { + ERROR_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): Too many handlers", handlerPtr, handlerArg); + retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS; // TODO: What's the proper error code for Apctl's TOO_MANY_HANDLERS? + return retval; + } + apctlHandlers[apctlHandlerCount++] = handler; + WARN_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): added handler %d", handlerPtr, handlerArg, apctlHandlerCount); + } + else + ERROR_LOG(HLE, "UNTESTED sceNetApctlAddHandler(%x, %x): Same handler already exists", handlerPtr, handlerArg); + + + // The id to return is the number of handlers currently registered + return retval; +} + +int sceNetApctlDelHandler(u32 handlerID) { + + if(apctlHandlers.find(handlerID) != apctlHandlers.end()) { + apctlHandlers.erase(handlerID); + apctlHandlerCount = apctlHandlerCount > 0? --apctlHandlerCount : 0; + WARN_LOG(HLE, "UNTESTED sceNetapctlDelHandler(%d): deleted handler %d", handlerID, handlerID); + } + else + ERROR_LOG(HLE, "UNTESTED sceNetapctlDelHandler(%d): asked to delete invalid handler %d", handlerID, handlerID); + + return 0; +} + + + const HLEFunction sceNet[] = { {0x39AF39A6, sceNetInit, "sceNetInit"}, {0x281928A9, WrapU_V, "sceNetTerm"}, @@ -444,7 +557,7 @@ const HLEFunction sceNetResolver[] = { }; const HLEFunction sceNetInet[] = { - {0x17943399, 0, "sceNetInetInit"}, + {0x17943399, WrapI_V, "sceNetInetInit"}, {0x2fe71fe7, 0, "sceNetInetSetsockopt"}, {0x410b34aa, 0, "sceNetInetConnect"}, {0x5be8d595, 0, "sceNetInetSelect"}, @@ -463,7 +576,7 @@ const HLEFunction sceNetInet[] = { {0xd10a1a7a, 0, "sceNetInetListen"}, {0xdb094e1b, 0, "sceNetInetAccept"}, {0x8ca3a97e, 0, "sceNetInetGetPspError"}, - {0xa9ed66b9, 0, "sceNetInetTerm"}, + {0xa9ed66b9, WrapI_V, "sceNetInetTerm"}, {0xE30B8C19, 0, "sceNetInetInetPton"}, {0xE247B6D6, 0, "sceNetInetGetpeername"}, {0x162e6fd5, 0, "sceNetInetGetsockname"}, @@ -481,10 +594,10 @@ const HLEFunction sceNetApctl[] = { {0xCFB957C6, 0, "sceNetApctlConnect"}, {0x24fe91a1, 0, "sceNetApctlDisconnect"}, {0x5deac81b, 0, "sceNetApctlGetState"}, - {0x8abadd51, 0, "sceNetApctlAddHandler"}, - {0xe2f91f9b, 0, "sceNetApctlInit"}, - {0x5963991b, 0, "sceNetApctlDelHandler"}, - {0xb3edd0ec, 0, "sceNetApctlTerm"}, + {0x8abadd51, WrapU_UU, "sceNetApctlAddHandler"}, + {0xe2f91f9b, WrapI_V, "sceNetApctlInit"}, + {0x5963991b, WrapI_U, "sceNetApctlDelHandler"}, + {0xb3edd0ec, WrapI_V, "sceNetApctlTerm"}, {0x2BEFDF23, 0, "sceNetApctlGetInfo"}, {0xa3e77e13, 0, "sceNetApctlScanSSID2"}, {0xf25a5006, 0, "sceNetApctlGetBSSDescIDList2"}, diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index 13f31e17da..0903e3d07a 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -71,6 +71,12 @@ int scePowerGetBatteryLifeTime() { return 0; } +int scePowerGetBatteryTemp() { + DEBUG_LOG(HLE, "0=scePowerGetBatteryTemp()"); + // 0 means celsius temperature of the battery + return 0; +} + int scePowerIsPowerOnline() { DEBUG_LOG(HLE, "1=scePowerIsPowerOnline"); return 1; @@ -314,7 +320,7 @@ static const HLEFunction scePower[] = { {0xFD18A0FF,0,"scePowerGetBatteryFullCapacity"}, {0x2085D15D,&WrapI_V,"scePowerGetBatteryLifePercent"}, {0x8EFB3FA2,&WrapI_V,"scePowerGetBatteryLifeTime"}, - {0x28E12023,0,"scePowerGetBatteryTemp"}, + {0x28E12023,&WrapI_V,"scePowerGetBatteryTemp"}, {0x862AE1A6,0,"scePowerGetBatteryElec"}, {0x483CE86B,0,"scePowerGetBatteryVolt"}, {0x23436A4A,0,"scePowerGetInnerTemp"}, diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 8253876bff..afe4fb2537 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -461,7 +461,7 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) param = g_Config.iDateFormat; break; case PSP_SYSTEMPARAM_ID_INT_TIME_FORMAT: - param = g_Config.itimeformat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR; + param = g_Config.iTimeFormat?PSP_SYSTEMPARAM_TIME_FORMAT_12HR:PSP_SYSTEMPARAM_TIME_FORMAT_24HR; break; case PSP_SYSTEMPARAM_ID_INT_TIMEZONE: param = g_Config.iTimeZone; @@ -473,7 +473,7 @@ u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) param = g_Config.ilanguage; break; case PSP_SYSTEMPARAM_ID_INT_BUTTON_PREFERENCE: - param = g_Config.bButtonPreference?PSP_SYSTEMPARAM_BUTTON_CROSS:PSP_SYSTEMPARAM_BUTTON_CIRCLE; + param = g_Config.iButtonPreference; break; case PSP_SYSTEMPARAM_ID_INT_LOCK_PARENTAL_LEVEL: param = g_Config.iLockParentalLevel; diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 60c5f3e626..f5a468bbaf 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -456,18 +456,27 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) { // Alright, all voices mixed. Let's convert and clip, and at the same time, wipe mixBuffer for next time. Could also dither. s16 *outp = (s16 *)Memory::GetPointer(outAddr); - s16 *inp = inAddr ? (s16*)Memory::GetPointer(inAddr) : 0; - for (int i = 0; i < grainSize * 2; i += 2) { - int sampleL = mixBuffer[i] + sendBuffer[i]; - if (inp) - sampleL += (*inp++) * leftVol >> 12; - *outp++ = clamp_s16(sampleL); - if (outputMode == 0) { - // stereo - int sampleR = mixBuffer[i + 1] + sendBuffer[i + 1]; + const s16 *inp = inAddr ? (s16*)Memory::GetPointer(inAddr) : 0; + if (outputMode == 0) { + if (inp) { + for (int i = 0; i < grainSize * 2; i += 2) { + int sampleL = mixBuffer[i] + sendBuffer[i] + ((*inp++) * leftVol >> 12); + int sampleR = mixBuffer[i + 1] + sendBuffer[i + 1] + ((*inp++) * rightVol >> 12); + *outp++ = clamp_s16(sampleL); + *outp++ = clamp_s16(sampleR); + } + } else { + for (int i = 0; i < grainSize * 2; i += 2) { + *outp++ = clamp_s16(mixBuffer[i] + sendBuffer[i]); + *outp++ = clamp_s16(mixBuffer[i + 1] + sendBuffer[i + 1]); + } + } + } else { + for (int i = 0; i < grainSize * 2; i += 2) { + int sampleL = mixBuffer[i] + sendBuffer[i]; if (inp) - sampleR += (*inp++) * rightVol >> 12; - *outp++ = clamp_s16(sampleR); + sampleL += (*inp++) * leftVol >> 12; + *outp++ = clamp_s16(sampleL); } } memset(mixBuffer, 0, grainSize * sizeof(int) * 2); diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index aa2bf444b3..f9a9e1714a 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -87,8 +87,10 @@ EmuFileType Identify_File(std::string &filename) if (id == 'FLE\x7F') { + // There are a few elfs misnamed as pbp (like Trig Wars), accept that. if (!strcasecmp(extension.c_str(), ".plf") || strstr(filename.c_str(),"BOOT.BIN") || - !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") ) + !strcasecmp(extension.c_str(), ".elf") || !strcasecmp(extension.c_str(), ".prx") || + !strcasecmp(extension.c_str(), ".pbp")) { return FILETYPE_PSP_ELF; } diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 8cbabbed25..32f22b8d17 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -211,7 +211,7 @@ namespace Reporting postdata.Add("pixel_height", PSP_CoreParameter().pixelHeight); postdata.Add("ticks", (const uint64_t)CoreTiming::GetTicks()); - if (g_Config.bShowFPSCounter) + if (g_Config.iShowFPSCounter) { float vps, fps; __DisplayGetAveragedFPS(&vps, &fps); diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index f1da2ea9c0..15225bf3c9 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -52,7 +52,7 @@ public: virtual void DumpNextFrame(); virtual void Flush(); virtual void DoState(PointerWrap &p); - + // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. virtual void Resized(); virtual bool DecodeTexture(u8* dest, GPUgstate state) diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 6ce57a7b89..3fb06b1df8 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -302,6 +302,7 @@ void GenerateFragmentShader(char *buffer) { #ifdef DEBUG_SHADER if (doTexture) { WRITE(p, " gl_FragColor = texture2D(tex, v_texcoord.xy);\n"); + WRITE(p, " gl_FragColor += vec4(0.3,0,0.3,0.3);\n"); } else { WRITE(p, " gl_FragColor = vec4(1,0,1,1);\n"); } diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 2f83bb05fa..9cabd91c87 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -88,7 +88,7 @@ void CenterRect(float *x, float *y, float *w, float *h, *x = 0.0f; *w = frameW; *h = frameW / origRatio; -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY // Stretch a little bit if (g_Config.bPartialStretch) *h = (frameH + *h) / 2.0f; // (408 + 720) / 2 = 564 @@ -269,8 +269,8 @@ void FramebufferManager::DrawActiveTexture(float x, float y, float w, float h, b VirtualFramebuffer *FramebufferManager::GetDisplayFBO() { VirtualFramebuffer *match = NULL; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { - VirtualFramebuffer *v = *iter; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *v = vfbs_[i]; if (MaskedEqual(v->fb_address, displayFramebufPtr_) && v->format == displayFormat_ && v->width >= 480) { // Could check w too but whatever if (match == NULL || match->last_frame_used < v->last_frame_used) { @@ -285,9 +285,9 @@ VirtualFramebuffer *FramebufferManager::GetDisplayFBO() { DEBUG_LOG(HLE, "Finding no FBO matching address %08x", displayFramebufPtr_); #if 0 // defined(_DEBUG) std::string debug = "FBOs: "; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { + for (size_t i = 0; i < vfbs_.size(); ++i) { char temp[256]; - sprintf(temp, "%08x %i %i", (*iter)->fb_address, (*iter)->width, (*iter)->height); + sprintf(temp, "%08x %i %i", vfbs_[i]->fb_address, vfbs_[i]->width, vfbs_[i]->height); debug += std::string(temp); } ERROR_LOG(HLE, "FBOs: %s", debug.c_str()); @@ -324,6 +324,26 @@ void GuessDrawingSize(int &drawing_width, int &drawing_height) { drawing_height = std::min(drawing_height, 512); } +void FramebufferManager::DestroyFramebuf(VirtualFramebuffer *v) { + textureCache_->NotifyFramebufferDestroyed(v->fb_address, v); + if (v->fbo) { + fbo_destroy(v->fbo); + v->fbo = 0; + } + + // Wipe some pointers + if (currentRenderVfb_ == v) + currentRenderVfb_ = 0; + if (displayFramebuf_ == v) + displayFramebuf_ = 0; + if (prevDisplayFramebuf_ == v) + prevDisplayFramebuf_ = 0; + if (prevPrevDisplayFramebuf_ == v) + prevPrevDisplayFramebuf_ = 0; + + delete v; +} + void FramebufferManager::SetRenderFrameBuffer() { if (!gstate_c.framebufChanged && currentRenderVfb_) { currentRenderVfb_->last_frame_used = gpuStats.numFrames; @@ -350,16 +370,36 @@ void FramebufferManager::SetRenderFrameBuffer() { int drawing_width, drawing_height; GuessDrawingSize(drawing_width, drawing_height); - // Find a matching framebuffer + int buffer_width = drawing_width; + int buffer_height = drawing_height; + + // Find a matching framebuffer, same size or bigger VirtualFramebuffer *vfb = 0; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { - VirtualFramebuffer *v = *iter; - if (MaskedEqual(v->fb_address, fb_address) && v->width == drawing_width && v->height == drawing_height && v->format == fmt) { - // Let's not be so picky for now. Let's say this is the one. - vfb = v; - // Update fb stride in case it changed - vfb->fb_stride = fb_stride; - break; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *v = vfbs_[i]; + if (MaskedEqual(v->fb_address, fb_address) && v->format == fmt) { + // Okay, let's check the sizes. If the new one is bigger than the old one, recreate. + // If the opposite, just use it and hope that the game sets scissors accordingly. + if (v->bufferWidth >= drawing_width && v->bufferHeight >= drawing_height) { + // Let's not be so picky for now. Let's say this is the one. + vfb = v; + // Update fb stride in case it changed + vfb->fb_stride = fb_stride; + // Just hack the width/height and we should be fine. also hack renderwidth/renderheight? + v->width = drawing_width; + v->height = drawing_height; + break; + } else { + INFO_LOG(HLE, "Embiggening framebuffer (%i, %i) -> (%i, %i)", (int)v->width, (int)v->height, drawing_width, drawing_height); + // drawing_width or drawing_height is bigger. Let's recreate with the max. + // To do this right we should copy the data over too, but meh. + buffer_width = std::max((int)v->width, drawing_width); + buffer_height = std::max((int)v->height, drawing_height); + + DestroyFramebuf(v); + vfbs_.erase(vfbs_.begin() + i--); + break; + } } } @@ -379,6 +419,8 @@ void FramebufferManager::SetRenderFrameBuffer() { vfb->height = drawing_height; vfb->renderWidth = (u16)(drawing_width * renderWidthFactor); vfb->renderHeight = (u16)(drawing_height * renderHeightFactor); + vfb->bufferWidth = buffer_width; + vfb->bufferHeight = buffer_height; vfb->format = fmt; vfb->usageFlags = FB_USAGE_RENDERTARGET; vfb->dirtyAfterDisplay = true; @@ -411,7 +453,11 @@ void FramebufferManager::SetRenderFrameBuffer() { if (useBufferedRendering_) { vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, vfb->colorDepth); - fbo_bind_as_render_target(vfb->fbo); + if (vfb->fbo) { + fbo_bind_as_render_target(vfb->fbo); + } else { + ERROR_LOG(HLE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); + } } else { fbo_unbind(); // Let's ignore rendering to targets that have not (yet) been displayed. @@ -609,8 +655,8 @@ void FramebufferManager::SetDisplayFramebuffer(u32 framebuf, u32 stride, int for std::vector FramebufferManager::GetFramebufferList() { std::vector list; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { - VirtualFramebuffer *vfb = *iter; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; FramebufferInfo info; info.fb_address = vfb->fb_address; @@ -628,26 +674,17 @@ std::vector FramebufferManager::GetFramebufferList() { void FramebufferManager::DecimateFBOs() { fbo_unbind(); currentRenderVfb_ = 0; - - for (auto iter = vfbs_.begin(); iter != vfbs_.end();) { - VirtualFramebuffer *vfb = *iter; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; if (vfb == displayFramebuf_ || vfb == prevDisplayFramebuf_ || vfb == prevPrevDisplayFramebuf_) { - ++iter; continue; } - int age = frameLastFramebufUsed - (*iter)->last_frame_used; + int age = frameLastFramebufUsed - vfb->last_frame_used; if (age > FBO_OLD_AGE) { - textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb); INFO_LOG(HLE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age) - if (vfb->fbo) { - fbo_destroy(vfb->fbo); - vfb->fbo = 0; - } - delete vfb; - vfbs_.erase(iter++); + DestroyFramebuf(vfb); + vfbs_.erase(vfbs_.begin() + i--); } - else - ++iter; } } @@ -658,15 +695,10 @@ void FramebufferManager::DestroyAllFBOs() { prevDisplayFramebuf_ = 0; prevPrevDisplayFramebuf_ = 0; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter) { - VirtualFramebuffer *vfb = *iter; - textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb); - if (vfb->fbo) { - INFO_LOG(HLE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); - fbo_destroy(vfb->fbo); - vfb->fbo = 0; - } - delete vfb; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; + INFO_LOG(HLE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); + DestroyFramebuf(vfb); } vfbs_.clear(); } @@ -685,8 +717,8 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size) { currentRenderVfb_ = 0; bool needUnbind = false; - for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ) { - VirtualFramebuffer *vfb = *iter; + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; if (MaskedEqual(vfb->fb_address, addr)) { // TODO: This without the fbo_unbind() above would be better than destroying the FBO. // However, it doesn't seem to work for Star Ocean, at least @@ -694,20 +726,12 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size) { fbo_bind_as_render_target(vfb->fbo); needUnbind = true; DrawPixels(Memory::GetPointer(addr), vfb->format, vfb->fb_stride); - ++iter; } else { - textureCache_->NotifyFramebufferDestroyed(vfb->fb_address, vfb); INFO_LOG(HLE, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format) - if (vfb->fbo) { - fbo_destroy(vfb->fbo); - vfb->fbo = 0; - } - delete vfb; - vfbs_.erase(iter++); + DestroyFramebuf(vfb); + vfbs_.erase(vfbs_.begin() + i--); } } - else - ++iter; } if (needUnbind) diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 9285cab997..8142e1949d 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -54,10 +54,16 @@ struct VirtualFramebuffer { int z_stride; // There's also a top left of the drawing region, but meh... + + // width/height: The detected size of the current framebuffer. u16 width; u16 height; + // renderWidth/renderHeight: The actual size we render at. May be scaled to render at higher resolutions. u16 renderWidth; u16 renderHeight; + // bufferWidth/bufferHeight: The actual (but non scaled) size of the buffer we render to. May only be bigger than width/height. + u16 bufferWidth; + u16 bufferHeight; u16 usageFlags; @@ -98,6 +104,7 @@ public: void CopyDisplayToOutput(); void SetRenderFrameBuffer(); // Uses parameters computed from gstate void UpdateFromMemory(u32 addr, int size); + // TODO: Break out into some form of FBO manager VirtualFramebuffer *GetDisplayFBO(); void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format); @@ -117,6 +124,8 @@ public: return displayFramebuf_ ? (0x04000000 | displayFramebuf_->fb_address) : 0; } + void DestroyFramebuf(VirtualFramebuffer *vfb); + private: u32 ramDisplayFramebufPtr_; // workaround for MotoGP insanity u32 displayFramebufPtr_; @@ -128,7 +137,7 @@ private: VirtualFramebuffer *prevPrevDisplayFramebuf_; int frameLastFramebufUsed; - std::list vfbs_; + std::vector vfbs_; VirtualFramebuffer *currentRenderVfb_; diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index c4ab5939c0..b727481bc9 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -390,7 +390,22 @@ void LinkedShader::updateUniforms() { for (int i = 0; i < 4; i++) { if (dirtyUniforms & (DIRTY_LIGHT0 << i)) { - if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]); + GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3); + if (type == GE_LIGHTTYPE_DIRECTIONAL) { + // Prenormalize + float x = gstate_c.lightpos[i][0]; + float y = gstate_c.lightpos[i][1]; + float z = gstate_c.lightpos[i][2]; + float len = sqrtf(x*x+y*y+z*z); + if (len == 0.0f) + len = 1.0f; + else + len = 1.0f / len; + float vec[3] = { x / len, y / len, z / len }; + if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, vec); + } else { + if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]); + } if (u_lightdir[i] != -1) glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]); if (u_lightatt[i] != -1) glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]); if (u_lightangle[i] != -1) glUniform1f(u_lightangle[i], gstate_c.lightangle[i]); diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 813be0caa8..4582fa18ca 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -265,8 +265,8 @@ void TransformDrawEngine::ApplyDrawState(int prim) { if (g_Config.bBufferedRendering) { renderX = 0; renderY = 0; - renderWidth = framebufferManager_->GetRenderWidth(); - renderHeight = framebufferManager_->GetRenderHeight(); + renderWidth = framebufferManager_->GetRenderWidth(); + renderHeight = framebufferManager_->GetRenderHeight(); renderWidthFactor = (float)renderWidth / framebufferManager_->GetTargetWidth(); renderHeightFactor = (float)renderHeight / framebufferManager_->GetTargetHeight(); } else { diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index b7aa7e2921..d2a3b83acc 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -75,8 +75,8 @@ TextureCache::~TextureCache() { void TextureCache::Clear(bool delete_them) { glBindTexture(GL_TEXTURE_2D, 0); + lastBoundTexture = -1; if (delete_them) { - lastBoundTexture = -1; for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ++iter) { DEBUG_LOG(G3D, "Deleting texture %i", iter->second.texture); glDeleteTextures(1, &iter->second.texture); @@ -96,6 +96,7 @@ void TextureCache::Clear(bool delete_them) { // Removes old textures. void TextureCache::Decimate() { glBindTexture(GL_TEXTURE_2D, 0); + lastBoundTexture = -1; int killAge = lowMemoryMode_ ? TEXTURE_KILL_AGE_LOWMEM : TEXTURE_KILL_AGE; for (TexCache::iterator iter = cache.begin(); iter != cache.end(); ) { if (iter->second.lastFrame + TEXTURE_KILL_AGE < gpuStats.numFrames) { @@ -492,6 +493,8 @@ void TextureCache::UpdateSamplingParams(TexCacheEntry &entry, bool force) { bool sClamp = gstate.texwrap & 1; bool tClamp = (gstate.texwrap>>8) & 1; + // bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001; // Fix texlevel at 0 + if (entry.maxLevel == 0) { // Enforce no mip filtering, for safety. minFilt &= 1; // no mipmaps yet @@ -702,6 +705,8 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, GLuint dstFmt, int n default: { // No need to convert RGBA8888, right order already + if (dst != src) + memcpy(dst, src, numPixels * sizeof(u32)); } break; } @@ -866,11 +871,62 @@ inline u32 TextureCache::GetCurrentClutHash() { return clutHash_; } +// #define DEBUG_TEXTURES + +#ifdef DEBUG_TEXTURES +bool SetDebugTexture() { + static const int highlightFrames = 30; + + static int numTextures = 0; + static int lastFrames = 0; + static int mostTextures = 1; + + if (lastFrames != gpuStats.numFrames) { + mostTextures = std::max(mostTextures, numTextures); + numTextures = 0; + lastFrames = gpuStats.numFrames; + } + + static GLuint solidTexture = 0; + + bool changed = false; + if (((gpuStats.numFrames / highlightFrames) % mostTextures) == numTextures) { + if (gpuStats.numFrames % highlightFrames == 0) { + NOTICE_LOG(HLE, "Highlighting texture # %d / %d", numTextures, mostTextures); + } + static const u32 solidTextureData[] = {0x99AA99FF}; + + if (solidTexture == 0) { + glGenTextures(1, &solidTexture); + glBindTexture(GL_TEXTURE_2D, solidTexture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, solidTextureData); + } else { + glBindTexture(GL_TEXTURE_2D, solidTexture); + } + changed = true; + } + + ++numTextures; + return changed; +} +#endif + void TextureCache::SetTexture() { +#ifdef DEBUG_TEXTURES + if (SetDebugTexture()) { + // A different texture was bound, let's rebind next time. + lastBoundTexture = -1; + return; + } +#endif + u32 texaddr = (gstate.texaddr[0] & 0xFFFFF0) | ((gstate.texbufwidth[0]<<8) & 0x0F000000); if (!Memory::IsValidAddress(texaddr)) { // Bind a null texture and return. glBindTexture(GL_TEXTURE_2D, 0); + lastBoundTexture = -1; return; } @@ -921,12 +977,14 @@ void TextureCache::SetTexture() { if (entry->framebuffer->fbo) entry->framebuffer->fbo = 0; glBindTexture(GL_TEXTURE_2D, 0); + lastBoundTexture = -1; entry->lastFrame = gpuStats.numFrames; } else { if (entry->framebuffer->fbo) { fbo_bind_color_as_texture(entry->framebuffer->fbo, 0); } else { glBindTexture(GL_TEXTURE_2D, 0); + lastBoundTexture = -1; gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE; } UpdateSamplingParams(*entry, false); diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 9c20120ef2..8d8c1d33c9 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -51,7 +51,7 @@ const GLuint glprim[8] = { enum { DECODED_VERTEX_BUFFER_SIZE = 65536 * 48, - DECODED_INDEX_BUFFER_SIZE = 65536 * 2, + DECODED_INDEX_BUFFER_SIZE = 65536 * 20, TRANSFORMED_VERTEX_BUFFER_SIZE = 65536 * sizeof(TransformedVertex) }; diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index 785e6db6b5..9ae40d540d 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -429,9 +429,10 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) { GELightComputation comp = (GELightComputation)(gstate.ltype[i] & 3); GELightType type = (GELightType)((gstate.ltype[i] >> 8) & 3); - if (type == GE_LIGHTTYPE_DIRECTIONAL) - WRITE(p, " toLight = normalize(u_lightpos%i);\n", i); - else { + if (type == GE_LIGHTTYPE_DIRECTIONAL) { + // We prenormalize light positions for directional lights. + WRITE(p, " toLight = u_lightpos%i;\n", i); + } else { WRITE(p, " toLight = u_lightpos%i - worldpos;\n", i); WRITE(p, " distance = length(toLight);\n"); WRITE(p, " toLight /= distance;\n"); diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index 384b1f5896..094d17aa8f 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -11,7 +11,11 @@ mobile_platform: MOBILITY += sensors symbian: MOBILITY += systeminfo # Libs -symbian: LIBS += -lCore.lib -lCommon.lib -lNative.lib +symbian { + LIBS += -lCore.lib -lCommon.lib -lNative.lib + # For now you have to copy these to the Symbian lib dir. Better solution coming later. + LIBS += -lavutil.lib -lavformat.lib -lavcodec.lib -lswresample.lib -lswscale.lib +} qnx: LIBS += -L. -lCore -lCommon -lNative -lscreen -lz win32 { CONFIG(release, debug|release) { diff --git a/Qt/Settings.pri b/Qt/Settings.pri index d527c478b4..c95e2633fe 100644 --- a/Qt/Settings.pri +++ b/Qt/Settings.pri @@ -37,13 +37,14 @@ contains(MEEGO_EDITION,harmattan)|!count(gleslib,0) { contains(MEEGO_EDITION,harmattan): DEFINES += MEEGO_EDITION_HARMATTAN "_SYS_UCONTEXT_H=1" qnx { # Use mkspec: unsupported/qws/qnx-armv7-g++ - DEFINES += BLACKBERRY BLACKBERRY10 "_QNX_SOURCE=1" "_C99=1" + DEFINES += BLACKBERRY "_QNX_SOURCE=1" "_C99=1" } symbian { # Does not seem to be a way to change to armv6 compile so just override in variants.xml (see README) MMP_RULES -= "ARMFPU softvfp+vfpv2" MMP_RULES += "ARMFPU vfpv2" - DEFINES += "BOOST_COMPILER_CONFIG=" + DEFINES += USE_FFMPEG __STDC_CONSTANT_MACROS "BOOST_COMPILER_CONFIG=" QMAKE_CXXFLAGS += -marm -Wno-parentheses -Wno-comment INCLUDEPATH += $$EPOCROOT/epoc32/include/stdapis/glib-2.0 + INCLUDEPATH += ../ffmpeg/symbian/armv6/include } diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 9e33b29969..97d350cc98 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -156,7 +156,7 @@ void MainWindow::UpdateMenus() ui->action_Sound->setChecked(g_Config.bEnableSound); ui->action_OptionsShowDebugStatistics->setChecked(g_Config.bShowDebugStats); - ui->action_Show_FPS_counter->setChecked(g_Config.bShowFPSCounter); + ui->action_Show_FPS_counter->setChecked(g_Config.iShowFPSCounter); ui->actionLogDefDebug->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LDEBUG); ui->actionLogDefInfo->setChecked(LogManager::GetInstance()->GetLogLevel(LogTypes::COMMON) == LogTypes::LINFO); @@ -629,7 +629,7 @@ void MainWindow::on_action_OptionsShowDebugStatistics_triggered() void MainWindow::on_action_Show_FPS_counter_triggered() { - g_Config.bShowFPSCounter = !g_Config.bShowFPSCounter; + g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter; UpdateMenus(); } diff --git a/README.md b/README.md index 6351b74f86..4dc3d0b3b3 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ You will need to add the GCCE 4.6.3 variant to Symbian\tools\sbs\lib\config\vari You will also need to increase the data section of the executable in linking stage by modifying Symbian\tools\sbs\lib\config\gcce.xml as follows: ``` - + ``` Then simply compile the PPSSPPQt.pro with `qmake` from the SDK or the included QtCreator. diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 5ce338c37d..3636cc027f 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -337,11 +337,18 @@ void EmuScreen::render() { ui_draw2d.SetFontScale(1.0f, 1.0f); } - if (g_Config.bShowFPSCounter) { + if (g_Config.iShowFPSCounter) { float vps, fps; __DisplayGetFPS(&vps, &fps); char fpsbuf[256]; - sprintf(fpsbuf, "VPS: %0.1f\nFPS: %0.1f", vps, fps); + switch (g_Config.iShowFPSCounter) { + case 1: + sprintf(fpsbuf, "VPS: %0.1f", vps); break; + case 2: + sprintf(fpsbuf, "FPS: %0.1f", fps); break; + case 3: + sprintf(fpsbuf, "VPS: %0.1f\nFPS: %0.1f", vps, fps); break; + } ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 8, 12, 0xc0000000, ALIGN_TOPRIGHT); ui_draw2d.DrawText(UBUNTU24, fpsbuf, dp_xres - 10, 10, 0xFF3fFF3f, ALIGN_TOPRIGHT); } diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index bfa8e8be6d..562dd99b4a 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -21,6 +21,7 @@ #include "base/timeutil.h" #include "base/stringutil.h" #include "file/file_util.h" +#include "file/zip_read.h" #include "image/png_load.h" #include "thread/prioritizedworkqueue.h" #include "GameInfoCache.h" @@ -181,15 +182,22 @@ public: if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) { pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->iconTextureData); } else { - // We should load a default image here. + // Read standard icon + size_t sz; + INFO_LOG(HLE, "Loading unknown.png because a PBP was missing an icon"); + uint8_t *contents = VFSReadFile("unknown.png", &sz); + if (contents) { + lock_guard lock(info_->lock); + info_->iconTextureData = std::string((const char *)contents, sz); + } + delete [] contents; } } if (info_->wantBG) { - { + if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); - if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) - pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); + pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); } } } @@ -199,38 +207,55 @@ public: info_->id = "ELF000000"; info_->id_version = "ELF000000_1.00"; info_->paramSFOLoaded = true; + + { + // Read standard icon + size_t sz; + uint8_t *contents = VFSReadFile("unknown.png", &sz); + INFO_LOG(HLE, "Loading unknown.png because there was an ELF"); + if (contents) { + lock_guard lock(info_->lock); + info_->iconTextureData = std::string((const char *)contents, sz); + } + delete [] contents; + } + return; case FILETYPE_PSP_ISO: case FILETYPE_PSP_ISO_NP: - info_->fileType = FILETYPE_PSP_ISO; - SequentialHandleAllocator handles; - // Let's assume it's an ISO. - // TODO: This will currently read in the whole directory tree. Not really necessary for just a - // few files. - BlockDevice *bd = constructBlockDevice(gamePath_.c_str()); - if (!bd) - return; // nothing to do here.. - ISOFileSystem umd(&handles, bd, "/PSP_GAME"); + { + info_->fileType = FILETYPE_PSP_ISO; + SequentialHandleAllocator handles; + // Let's assume it's an ISO. + // TODO: This will currently read in the whole directory tree. Not really necessary for just a + // few files. + BlockDevice *bd = constructBlockDevice(gamePath_.c_str()); + if (!bd) + return; // nothing to do here.. + ISOFileSystem umd(&handles, bd, "/PSP_GAME"); - // Alright, let's fetch the PARAM.SFO. - std::string paramSFOcontents; - if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { - lock_guard lock(info_->lock); - info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); - info_->title = info_->paramSFO.GetValueString("TITLE"); - info_->id = info_->paramSFO.GetValueString("DISC_ID"); - info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); + // Alright, let's fetch the PARAM.SFO. + std::string paramSFOcontents; + if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) { + lock_guard lock(info_->lock); + info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); + info_->title = info_->paramSFO.GetValueString("TITLE"); + info_->id = info_->paramSFO.GetValueString("DISC_ID"); + info_->id_version = info_->paramSFO.GetValueString("DISC_ID") + "_" + info_->paramSFO.GetValueString("DISC_VERSION"); - info_->paramSFOLoaded = true; + info_->paramSFOLoaded = true; + } + + ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); + if (info_->wantBG) { + ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); + } + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); + break; } - - ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); - if (info_->wantBG) { - ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); - } - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); - + default: + ; } // probably only want these when we ask for the background image... // should maybe flip the flag to "onlyIcon" diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index 6b551277c9..9fe31e893e 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -306,7 +306,7 @@ void MenuScreen::render() { // This might create a texture so we must flush first. UIFlush(); GameInfo *ginfo = g_gameInfoCache.GetInfo(g_Config.recentIsos[i], false); - if (ginfo && ginfo->fileType != FILETYPE_PSP_ELF) { + if (ginfo) { u32 color; if (ginfo->iconTexture == 0) { color = 0; @@ -454,7 +454,7 @@ void PauseScreen::render() { UICheckBox(GEN_ID, x, y += stride, a->T("Enable Sound"), ALIGN_TOPLEFT, &g_Config.bEnableSound); // TODO: Maybe shouldn't show this if the screen ratios are very close... -#ifdef BLACKBERRY10 +#ifdef BLACKBERRY if (pixel_xres == pixel_yres) UICheckBox(GEN_ID, x, y += stride, gs->T("Partial Vertical Stretch"), ALIGN_TOPLEFT, &g_Config.bPartialStretch); #endif @@ -465,8 +465,6 @@ void PauseScreen::render() { if (gpu) gpu->Resized(); } - 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 , gs->T("Frame Skipping"), ALIGN_TOPLEFT, &enableFrameSkip); if (enableFrameSkip) { @@ -485,12 +483,13 @@ void PauseScreen::render() { 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; - ui_draw2d.DrawText(UBUNTU24, gs->T("Save State :"), 30, 360, 0xFFFFFFFF, ALIGN_LEFT); - HLinear hlinear4(x + 180 , y += 50, 10); + UICheckBox(GEN_ID, x, y += stride, gs->T("Linear Filtering"), ALIGN_TOPLEFT, &g_Config.bLinearFiltering); + ui_draw2d.DrawText(UBUNTU24, gs->T("Save State :"), 30, y += 40, 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear4(x + 180 , y , 10); if (UIButton(GEN_ID, hlinear4, 60, 0, "1", ALIGN_LEFT)) { SaveState::SaveSlot(0, 0, 0); screenManager()->finishDialog(this, DR_CANCEL); @@ -512,9 +511,8 @@ void PauseScreen::render() { screenManager()->finishDialog(this, DR_CANCEL); } - - ui_draw2d.DrawText(UBUNTU24, gs->T("Load State :"), 30, 420, 0xFFFFFFFF, ALIGN_LEFT); - HLinear hlinear3(x + 180 , y += 60, 10); + ui_draw2d.DrawText(UBUNTU24, gs->T("Load State :"), 30, y += 60, 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear3(x + 180 , y + 10 , 10); if (UIButton(GEN_ID, hlinear3, 60, 0, "1", ALIGN_LEFT)) { SaveState::LoadSlot(0, 0, 0); screenManager()->finishDialog(this, DR_CANCEL); @@ -686,27 +684,31 @@ void DeveloperScreen::render() { screenManager()->finishDialog(this, DR_OK); } - if (UIButton(GEN_ID, vlinear, w, 0, d->T("Load language ini"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Load language ini"), ALIGN_LEFT)) { i18nrepo.LoadIni(g_Config.languageIni); // After this, g and s are no longer valid. Need to reload them. g = GetI18NCategory("General"); d = GetI18NCategory("Developer"); } - if (UIButton(GEN_ID, vlinear, w, 0, d->T("Save language ini"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Save language ini"), ALIGN_LEFT)) { i18nrepo.SaveIni(g_Config.languageIni); } - if (UIButton(GEN_ID, vlinear, w, 0, d->T("Run CPU tests"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Run CPU Tests"), ALIGN_LEFT)) { // TODO: Run tests RunTests(); // screenManager()->push(new EmuScreen()) } - if (UIButton(GEN_ID, vlinear, w, 0, d->T("Dump frame to log"), ALIGN_LEFT)) { + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Dump next frame"), ALIGN_LEFT)) { gpu->DumpNextFrame(); } + if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH + 80, 0, d->T("Cleanup Recents"), ALIGN_LEFT)) { + g_Config.recentIsos.clear(); + } + UIEnd(); } @@ -897,7 +899,12 @@ void GraphicsScreenP2::render() { g_Config.iTexScalingLevel = 2; if (UIButton(GEN_ID, hlinear2, 45, 0, gs->T("3x"), ALIGN_LEFT)) g_Config.iTexScalingLevel = 3; - +#ifdef _WIN32 + if (UIButton(GEN_ID, hlinear2, 45, 0, gs->T("4x"), ALIGN_LEFT)) + g_Config.iTexScalingLevel = 4; + if (UIButton(GEN_ID, hlinear2, 45, 0, gs->T("5x"), ALIGN_LEFT)) + g_Config.iTexScalingLevel = 5; +#endif UICheckBox(GEN_ID, x + 60, y += stride + 20, gs->T("Deposterize"), ALIGN_LEFT, &g_Config.bTexDeposterize); } else g_Config.iTexScalingLevel = 1; @@ -933,7 +940,35 @@ void GraphicsScreenP3::render() { int y = 35; int stride = 40; int columnw = 400; + + bool ShowCounter = g_Config.iShowFPSCounter > 0; + UICheckBox(GEN_ID, x, y += stride, gs->T("Show VPS/FPS"), ALIGN_TOPLEFT, &ShowCounter); + if (ShowCounter) { + if (g_Config.iShowFPSCounter <= 0) + g_Config.iShowFPSCounter = 1; + char counter[256]; + std::string type; + + switch (g_Config.iShowFPSCounter) { + case 1: type = "VPS";break; + case 2: type = "FPS";break; + case 3: type = "Both";break; + } + sprintf(counter, "%s %s", gs->T("Format :"), type.c_str()); + ui_draw2d.DrawText(UBUNTU24, counter, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 250, y, 20); + if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("VPS"), ALIGN_LEFT)) + g_Config.iShowFPSCounter = 1; + if (UIButton(GEN_ID, hlinear1, 80, 0, gs->T("FPS"), ALIGN_LEFT)) + g_Config.iShowFPSCounter = 2; + if (UIButton(GEN_ID, hlinear1, 90, 0, gs->T("Both"), ALIGN_LEFT)) + g_Config.iShowFPSCounter = 3; + + y += 20; + } else + g_Config.iShowFPSCounter = 0; + bool FpsLimit = g_Config.iFpsLimit != 0; UICheckBox(GEN_ID, x, y += stride, gs->T("FPS Limit"), ALIGN_TOPLEFT, &FpsLimit); if (FpsLimit) { @@ -1013,10 +1048,10 @@ void LanguageScreen::render() { screenManager()->finishDialog(this, DR_OK); } - int buttonW = LARGE_BUTTON_WIDTH - 50; + int buttonW = LARGE_BUTTON_WIDTH - 30; if (small) { - buttonW = LARGE_BUTTON_WIDTH - 70; + buttonW = LARGE_BUTTON_WIDTH - 50; } VGrid vlang(20, small ? 20 : 100, dp_yres - 50, 10, 10); @@ -1134,13 +1169,85 @@ void SystemScreen::render() { #endif if (g_Config.bJit) UICheckBox(GEN_ID, x, y += stride, s->T("Fast Memory", "Fast Memory (unstable)"), ALIGN_TOPLEFT, &g_Config.bFastMemory); - UICheckBox(GEN_ID, x, y += stride, s->T("Show FPS"), ALIGN_TOPLEFT, &g_Config.bShowFPSCounter); - UICheckBox(GEN_ID, x, y += stride, s->T("Encrypt Save"), ALIGN_TOPLEFT, &g_Config.bEncryptSave); - UICheckBox(GEN_ID, x, y += stride, s->T("Use Button X to Confirm"), ALIGN_TOPLEFT, &g_Config.bButtonPreference); - bool tf = g_Config.itimeformat == 1; - if (UICheckBox(GEN_ID, x, y += stride, s->T("12HR Time Format"), ALIGN_TOPLEFT, &tf)) { - g_Config.itimeformat = tf ? 1 : 0; + + //UICheckBox(GEN_ID, x, y += stride, s->T("Daylight Savings"), ALIGN_TOPLEFT, &g_Config.bDayLightSavings); + + const char *buttonPreferenceTitle; + switch (g_Config.iButtonPreference) { + case PSP_SYSTEMPARAM_BUTTON_CIRCLE: + buttonPreferenceTitle = s->T("Button Preference - O to Confirm"); + break; + case PSP_SYSTEMPARAM_BUTTON_CROSS: + default: + buttonPreferenceTitle = s->T("Button Preference - X to Confirm"); + break; } + +#ifdef _WIN32 + const int checkboxH = 32; +#else + const int checkboxH = 48; +#endif + ui_draw2d.DrawTextShadow(UBUNTU24, buttonPreferenceTitle, x + UI_SPACE + 29, (y += stride) + checkboxH / 2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER); + y += stride; + // 29 is the width of the checkbox, new UI will replace. + HLinear hlinearButtonPref(x + UI_SPACE + 29, y, 20); + if (UIButton(GEN_ID, hlinearButtonPref, 90, 0, s->T("Use O"), ALIGN_LEFT)) + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CIRCLE; + if (UIButton(GEN_ID, hlinearButtonPref, 90, 0, s->T("Use X"), ALIGN_LEFT)) + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS; + y += 20 + 6; + + /* + bool time = g_Config.iTimeFormat > 0 ; + UICheckBox(GEN_ID, x, y += stride, s->T("Time Format"), ALIGN_TOPLEFT, &time); + if (time) { + if (g_Config.iTimeFormat <= 0) + g_Config.iTimeFormat = 1; + + char button[256]; + std::string type; + switch (g_Config.iTimeFormat) { + case 1: type = "12HR";break; + case 2: type = "24HR";break; + } + sprintf(button, "%s %s", s->T("Format :"), type.c_str()); + ui_draw2d.DrawText(UBUNTU24, button, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 280, y, 20); + if (UIButton(GEN_ID, hlinear1, 80, 0, s->T("12HR"), ALIGN_LEFT)) + g_Config.iTimeFormat = 1; + if (UIButton(GEN_ID, hlinear1, 80, 0, s->T("24HR"), ALIGN_LEFT)) + g_Config.iTimeFormat = 2; + y += 10; + } else + g_Config.iTimeFormat = 0 ; + + bool date = g_Config.iDateFormat > 0; + UICheckBox(GEN_ID, x, y += stride, s->T("Date Format"), ALIGN_TOPLEFT, &date); + if (date) { + if (g_Config.iDateFormat <= 0) + g_Config.iDateFormat = 1; + char button[256]; + std::string type; + switch (g_Config.iDateFormat) { + case 1: type = "YYYYMMDD";break; + case 2: type = "MMDDYYYY";break; + case 3: type = "DDMMYYYY";break; + } + sprintf(button, "%s %s", s->T("Format :"), type.c_str()); + ui_draw2d.DrawText(UBUNTU24, button, x + 60, y += stride , 0xFFFFFFFF, ALIGN_LEFT); + HLinear hlinear1(x + 350, y, 10); + if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("YMD"), ALIGN_LEFT)) + g_Config.iDateFormat = 1; + if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("MDY"), ALIGN_LEFT)) + g_Config.iDateFormat = 2; + if (UIButton(GEN_ID, hlinear1, 70, 0, s->T("DMY"), ALIGN_LEFT)) + g_Config.iDateFormat = 3; + y += 10; + } else + g_Config.iDateFormat = 0; + */ + UICheckBox(GEN_ID, x, y += stride, s->T("Enable Cheats"), ALIGN_TOPLEFT, &g_Config.bEnableCheats); if (g_Config.bEnableCheats) { HLinear hlinear1(x + 60, y += stride + 10, 20); @@ -1151,7 +1258,7 @@ void SystemScreen::render() { HLinear hlinear2(x, y += stride + 10, 20); if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, s->T("Language"), ALIGN_TOPLEFT)) { screenManager()->push(new LanguageScreen()); - } + } UIEnd(); } @@ -1178,7 +1285,9 @@ void ControlsScreen::render() { int columnw = 440; UICheckBox(GEN_ID, x, y += stride, c->T("OnScreen", "On-Screen Touch Controls"), ALIGN_TOPLEFT, &g_Config.bShowTouchControls); + UICheckBox(GEN_ID, x, y += stride, c->T("Tilt", "Tilt to Analog (horizontal)"), ALIGN_TOPLEFT, &g_Config.bAccelerometerToAnalogHoriz); if (g_Config.bShowTouchControls) { + UICheckBox(GEN_ID, x, y += stride, c->T("Show Analog Stick"), ALIGN_TOPLEFT, &g_Config.bShowAnalogStick); UICheckBox(GEN_ID, x, y += stride, c->T("Buttons Scaling"), ALIGN_TOPLEFT, &g_Config.bLargeControls); if (g_Config.bLargeControls) { char scale[256]; @@ -1195,11 +1304,10 @@ void ControlsScreen::render() { g_Config.fButtonScale += 0.1; y += 20; } - UICheckBox(GEN_ID, x, y += stride, c->T("Show Analog Stick"), ALIGN_TOPLEFT, &g_Config.bShowAnalogStick); // This will be a slider in the new UI later bool bTransparent = g_Config.iTouchButtonOpacity < 65; bool prev = bTransparent; - UICheckBox(GEN_ID, x, y += stride, c->T("Transparent Buttons"), ALIGN_TOPLEFT, &bTransparent); + UICheckBox(GEN_ID, x, y += stride, c->T("Buttons Opacity"), ALIGN_TOPLEFT, &bTransparent); if (bTransparent) { char opacity[256]; sprintf(opacity, "%s %d", c->T("Opacity :"), g_Config.iTouchButtonOpacity); @@ -1218,7 +1326,6 @@ void ControlsScreen::render() { if (bTransparent != prev) g_Config.iTouchButtonOpacity = bTransparent ? 15 : 65; } - UICheckBox(GEN_ID, x, y += stride, c->T("Tilt", "Tilt to Analog (horizontal)"), ALIGN_TOPLEFT, &g_Config.bAccelerometerToAnalogHoriz); UIEnd(); } @@ -1423,7 +1530,7 @@ static const char * credits[] = { "PPSSPP is intended for educational purposes only.", "", "Please make sure that you own the rights to any games", - "you play by owning the UMD or buying the digital", + "you play by owning the UMD or by buying the digital", "download from the PSN store on your real PSP.", "", "", diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 7b4adda767..26d3bb0760 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -34,6 +34,7 @@ #include "base/NativeApp.h" #include "file/vfs.h" #include "file/zip_read.h" +#include "ext/jpge/jpge.h" #include "gfx_es2/gl_state.h" #include "gfx/gl_lost_manager.h" #include "gfx/texture.h" @@ -64,6 +65,7 @@ #include "UIShader.h" #include "UI/PluginScreen.h" +#include "UI/OnScreenDisplay.h" // The new UI framework, for initialization @@ -87,6 +89,8 @@ std::string game_title; bool isJailed; #endif +// Really need to clean this mess of globals up... but instead I add more :P +bool g_TakeScreenshot; recursive_mutex pendingMutex; static bool isMessagePending; @@ -445,6 +449,45 @@ void NativeInitGraphics() { glstate.viewport.set(0, 0, pixel_xres, pixel_yres); } +void TakeScreenshot() { +#ifdef _WIN32 + g_TakeScreenshot = false; + mkDir("screenshots"); + + // First, find a free filename. + int i = 0; + + char temp[256]; + while (i < 10000) { + sprintf(temp, "screenshots/screen%05d.jpg", i); + FileInfo info; + if (!getFileInfo(temp, &info)) + break; + i++; + } + + // Okay, allocate a buffer. + u8 *buffer = new u8[4 * pixel_xres * pixel_yres]; + // Silly openGL reads upside down, we flip to another buffer for simplicity. + u8 *flipbuffer = new u8[4 * pixel_xres * pixel_yres]; + + glReadPixels(0, 0, pixel_xres, pixel_yres, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + + for (int y = 0; y < pixel_yres; y++) { + memcpy(flipbuffer + y * pixel_xres * 4, buffer + (pixel_yres - y - 1) * pixel_xres * 4, pixel_xres * 4); + } + + jpge::params params; + params.m_quality = 90; + compress_image_to_jpeg_file(temp, pixel_xres, pixel_yres, 4, flipbuffer, params); + + delete [] buffer; + delete [] flipbuffer; + + osm.Show(temp); +#endif +} + void NativeRender() { EnableFZ(); @@ -464,6 +507,10 @@ void NativeRender() { glUniformMatrix4fv(UIShader_Get()->u_worldviewproj, 1, GL_FALSE, ortho.getReadPtr()); screenManager->render(); + + if (g_TakeScreenshot) { + TakeScreenshot(); + } } void NativeUpdate(InputState &input) { diff --git a/UI/PluginScreen.cpp b/UI/PluginScreen.cpp index bbc37c8b2c..8fb535b6ae 100644 --- a/UI/PluginScreen.cpp +++ b/UI/PluginScreen.cpp @@ -55,7 +55,7 @@ void PluginScreen::CreateViews() { Margins textMargins(20,17); Margins buttonMargins(10,10); - root_->Add(new TextView(UBUNTU24, "Atrac3+ Audio Decoding Support", ALIGN_HCENTER, 1.0f, new LinearLayoutParams(textMargins))); + root_->Add(new TextView(UBUNTU24, "Atrac3+ Audio Support", ALIGN_HCENTER, 1.5f, new LinearLayoutParams(textMargins))); ViewGroup *scroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); LinearLayout *scrollContents = new LinearLayout(ORIENT_VERTICAL); @@ -66,11 +66,11 @@ void PluginScreen::CreateViews() { const char *legalityNotice = p->T("Origins are dubious", "* Mai's Atrac3+ decoder is currently required\n" - "for audio in many games.\n" + "for background audio and voice in many games.\n" "Please note that the origins of this code are dubious.\n" "Choose More Information for more information."); - scrollContents->Add(new TextView(0, legalityNotice, ALIGN_LEFT, 1.0f, new LinearLayoutParams(textMargins) )); + scrollContents->Add(new TextView(0, legalityNotice, ALIGN_LEFT, 0.65f, new LinearLayoutParams(textMargins) )); progress_ = root_->Add(new ProgressBar()); progress_->SetVisibility(V_GONE); diff --git a/Windows/DSoundStream.cpp b/Windows/DSoundStream.cpp index 45047172bf..f2e83c8b76 100644 --- a/Windows/DSoundStream.cpp +++ b/Windows/DSoundStream.cpp @@ -49,7 +49,7 @@ namespace DSound pcmwf.wBitsPerSample = 16; dsbdesc.dwSize = sizeof(DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; // //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; // //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //change to set buffer size dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&pcmwf; diff --git a/Windows/DinputDevice.cpp b/Windows/DinputDevice.cpp index f39e0d3bb1..cc0222578e 100644 --- a/Windows/DinputDevice.cpp +++ b/Windows/DinputDevice.cpp @@ -210,6 +210,35 @@ int DinputDevice::UpdateState(InputState &input_state) } } + const LONG rthreshold = 8000; + + switch (g_Config.iRightStickBind) { + case 0: + break; + case 1: + if (js.lRz > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RIGHT; + else if (js.lRz < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LEFT; + if (js.lZ > rthreshold) input_state.pad_buttons |= PAD_BUTTON_UP; + else if (js.lZ < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_DOWN; + break; + case 2: + if (js.lRz > rthreshold) input_state.pad_buttons |= PAD_BUTTON_B; + else if (js.lRz < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_X; + if (js.lZ > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y; + else if (js.lZ < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A; + break; + case 3: + if (js.lRz > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; + else if (js.lRz < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; + break; + case 4: + if (js.lRz > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; + else if (js.lRz < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; + if (js.lZ > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y; + else if (js.lZ < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A; + break; + } + return UPDATESTATE_SKIP_PAD; } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index cb0be4f817..eb78ec2a6b 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -150,8 +150,8 @@ unsigned int WINAPI TheThread(void *) shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); - host = nativeHost; NativeShutdownGraphics(); + host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGL(); diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 30b107f124..378c2911fd 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -47,7 +47,7 @@ BOOL g_bFullScreen = FALSE; static RECT g_normalRC = {0}; - +extern bool g_TakeScreenshot; extern InputState input_state; extern const char * getVirtualKeyName(unsigned char key); extern const char * getXinputButtonName(unsigned int button); @@ -726,7 +726,7 @@ namespace MainWindow g_Config.bVertexCache = !g_Config.bVertexCache; break; case ID_OPTIONS_SHOWFPS: - g_Config.bShowFPSCounter = !g_Config.bShowFPSCounter; + g_Config.iShowFPSCounter = !g_Config.iShowFPSCounter; break; case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER: g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; @@ -776,6 +776,9 @@ namespace MainWindow DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); DialogManager::EnableAll(TRUE); break; + case ID_DEBUG_TAKESCREENSHOT: + g_TakeScreenshot = true; + break; default: MessageBox(hwndMain,"Unimplemented","Sorry",0); @@ -904,7 +907,7 @@ namespace MainWindow CHECKITEM(ID_EMULATION_RUNONLOAD, g_Config.bAutoRun); CHECKITEM(ID_OPTIONS_USEVBO, g_Config.bUseVBO); CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache); - CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.bShowFPSCounter); + CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.iShowFPSCounter); CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != 0); CHECKITEM(ID_OPTIONS_MIPMAP, g_Config.bMipMap); CHECKITEM(ID_OPTIONS_VSYNC, g_Config.iVSyncInterval != 0); diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 90cfc0505b..c1a25a3c6d 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -193,6 +193,12 @@ void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) { if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; break; + case 4: + if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; + else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; + if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y; + else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A; + break; } } diff --git a/Windows/ppsspp.ico b/Windows/ppsspp.ico index 1ad99792e3..52e667cdc4 100644 Binary files a/Windows/ppsspp.ico and b/Windows/ppsspp.ico differ diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 053d58e2e7..943473b640 100644 Binary files a/Windows/ppsspp.rc and b/Windows/ppsspp.rc differ diff --git a/Windows/resource.h b/Windows/resource.h index 328dd7e8a2..1613f9aa7c 100644 Binary files a/Windows/resource.h and b/Windows/resource.h differ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 6637a86515..bf49832017 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,8 +1,8 @@ diff --git a/android/jni/Android.mk b/android/jni/Android.mk index f85dd14969..ab1e76df51 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -5,7 +5,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := native_audio -LOCAL_CFLAGS := -O2 -fsigned-char -ffast-math -Wall -Wno-multichar -Wno-psabi +LOCAL_CFLAGS := -O3 -fsigned-char -ffast-math -Wall -Wno-multichar -Wno-psabi # yes, it's really CPPFLAGS for C++ LOCAL_CPPFLAGS := -std=gnu++11 -fno-rtti NATIVE := ../../native diff --git a/android/res/drawable-hdpi/ic_launcher.png b/android/res/drawable-hdpi/ic_launcher.png index 99e96d00e2..5f52b44ea6 100644 Binary files a/android/res/drawable-hdpi/ic_launcher.png and b/android/res/drawable-hdpi/ic_launcher.png differ diff --git a/android/res/drawable-ldpi/ic_launcher.png b/android/res/drawable-ldpi/ic_launcher.png index 57ab20ecda..2f4d54c286 100644 Binary files a/android/res/drawable-ldpi/ic_launcher.png and b/android/res/drawable-ldpi/ic_launcher.png differ diff --git a/android/res/drawable-mdpi/ic_launcher.png b/android/res/drawable-mdpi/ic_launcher.png index 75f936ed1d..854af501a5 100644 Binary files a/android/res/drawable-mdpi/ic_launcher.png and b/android/res/drawable-mdpi/ic_launcher.png differ diff --git a/android/res/drawable-xhdpi/ic_launcher.png b/android/res/drawable-xhdpi/ic_launcher.png index d59290c61b..9cd5e36b88 100644 Binary files a/android/res/drawable-xhdpi/ic_launcher.png and b/android/res/drawable-xhdpi/ic_launcher.png differ diff --git a/android/res/drawable-xxhdpi/ic_launcher.png b/android/res/drawable-xxhdpi/ic_launcher.png index 3fe685c43e..4877ac283a 100644 Binary files a/android/res/drawable-xxhdpi/ic_launcher.png and b/android/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/headless/Headless.cpp b/headless/Headless.cpp index af2375fe67..5bba70a795 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -200,12 +200,12 @@ int main(int argc, const char* argv[]) g_Config.bVertexCache = true; g_Config.bTrueColor = true; g_Config.ilanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; - g_Config.itimeformat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; + g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; g_Config.bEncryptSave = true; g_Config.sNickName = "shadow"; g_Config.iTimeZone = 60; g_Config.iDateFormat = PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY; - g_Config.bButtonPreference = true; + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS; g_Config.iLockParentalLevel = 9; #if defined(ANDROID)