diff --git a/Common/Data/Text/Parsers.cpp b/Common/Data/Text/Parsers.cpp index d8254151f4..8f1689a193 100644 --- a/Common/Data/Text/Parsers.cpp +++ b/Common/Data/Text/Parsers.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -166,7 +167,8 @@ StringWriter &StringWriter::F(const char *format, ...) { } va_list args; va_start(args, format); - p_ += vsnprintf(p_, remainder, format, args); + int wouldHaveBeenWritten = vsnprintf(p_, remainder, format, args); + p_ += std::min((int)remainder, wouldHaveBeenWritten); va_end(args); return *this; } diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 735b1299cc..62eb3c1158 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -149,6 +149,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "ForceEnableGPUReadback", &flags_.ForceEnableGPUReadback); CheckSetting(iniFile, gameID, "UseFFMPEGFindStreamInfo", &flags_.UseFFMPEGFindStreamInfo); CheckSetting(iniFile, gameID, "SoftwareRasterDepth", &flags_.SoftwareRasterDepth); + CheckSetting(iniFile, gameID, "DisableHLESceFont", &flags_.DisableHLESceFont); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index b865becff7..520c4ef6c5 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -112,6 +112,7 @@ struct CompatFlags { bool ForceEnableGPUReadback; bool UseFFMPEGFindStreamInfo; bool SoftwareRasterDepth; + bool DisableHLESceFont; }; struct VRCompat { diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index 85096ab877..3e0841f823 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -124,9 +124,8 @@ enum class DisableHLEFlags : int { scePsmfPlayer = (1 << 3), sceMpeg = (1 << 4), sceMp3 = (1 << 5), - sceJpeg = (1 << 6), - sceParseHttp = (1 << 7), - Count = 8, + sceParseHttp = (1 << 6), + Count = 7, // TODO: Some of the networking libraries may be interesting candidates, like HTTP. }; ENUM_CLASS_BITOPS(DisableHLEFlags); diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index d63b7cc94d..719e61afe4 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -122,6 +122,7 @@ static const HLEModuleMeta g_moduleMeta[] = { {"SceFont_Library", "sceLibFttt", DisableHLEFlags::sceFont}, {"SceHttp_Library", "sceHttp"}, {"sceMpeg_library", "sceMpeg", DisableHLEFlags::sceMpeg}, + {"sceMp3_Library", "sceMp3", DisableHLEFlags::sceMp3}, {"sceNetAdhocctl_Library"}, {"sceNetAdhocDownload_Library"}, {"sceNetAdhocMatching_Library"}, @@ -154,9 +155,9 @@ static const HLEModuleMeta g_moduleMeta[] = { {"SceParseHTTPheader_Library", "sceParseHttp", DisableHLEFlags::sceParseHttp}, {"SceParseURI_Library"}, // Guessing these names - {"sceJpeg", "sceJpeg", DisableHLEFlags::sceJpeg}, - {"sceJpeg_library", "sceJpeg", DisableHLEFlags::sceJpeg}, - {"sceJpeg_Library", "sceJpeg", DisableHLEFlags::sceJpeg}, + {"sceJpeg", "sceJpeg"}, + {"sceJpeg_library", "sceJpeg"}, + {"sceJpeg_Library", "sceJpeg"}, }; const HLEModuleMeta *GetHLEModuleMeta(std::string_view modname) { @@ -186,20 +187,39 @@ const HLEModuleMeta *GetHLEModuleMetaByImport(std::string_view importModuleName) return nullptr; } +DisableHLEFlags AlwaysDisableHLEFlags() { + // Once a module seems stable to load properly, we'll graduate it here. + // This will hide the checkbox, too. + // return DisableHLEFlags::scePsmf | DisableHLEFlags::scePsmfPlayer; + return (DisableHLEFlags)0; +} + +// Process compat flags. +static DisableHLEFlags GetDisableHLEFlags() { + DisableHLEFlags flags = (DisableHLEFlags)g_Config.iDisableHLE | AlwaysDisableHLEFlags(); + if (PSP_CoreParameter().compat.flags().DisableHLESceFont) { + flags |= DisableHLEFlags::sceFont; + } + return flags; +} + // Note: name is the modname from prx, not the export module name! -bool ShouldHLEModule(std::string_view modname, bool *wasDisabled) { - if (wasDisabled) { - *wasDisabled = false; +bool ShouldHLEModule(std::string_view modname, bool *wasDisabledManually) { + if (wasDisabledManually) { + *wasDisabledManually = false; } const HLEModuleMeta *meta = GetHLEModuleMeta(modname); if (!meta) { return false; } - bool disabled = meta->disableFlag & (DisableHLEFlags)g_Config.iDisableHLE; + bool disabled = meta->disableFlag & GetDisableHLEFlags(); if (disabled) { - if (wasDisabled) { - *wasDisabled = true; + if (wasDisabledManually) { + // We don't show notifications if a flag has "graduated". + if (!(meta->disableFlag & AlwaysDisableHLEFlags())) { + *wasDisabledManually = true; + } } return false; } @@ -210,7 +230,7 @@ bool ShouldHLEModuleByImportName(std::string_view name) { // Check our special metadata lookup. Should probably be merged with the main one. const HLEModuleMeta *meta = GetHLEModuleMetaByImport(name); if (meta) { - bool disabled = meta->disableFlag & (DisableHLEFlags)g_Config.iDisableHLE; + bool disabled = meta->disableFlag & GetDisableHLEFlags(); return !disabled; } diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 60e892b479..2a71089264 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -107,7 +107,7 @@ struct HLEModuleMeta { const HLEModuleMeta *GetHLEModuleMetaByFlag(DisableHLEFlags flag); const HLEModuleMeta *GetHLEModuleMeta(std::string_view modname); -bool ShouldHLEModule(std::string_view modname, bool *wasDisabled = nullptr); +bool ShouldHLEModule(std::string_view modname, bool *wasDisabledManually = nullptr); bool ShouldHLEModuleByImportName(std::string_view importModuleName); const char *GetHLEFuncName(std::string_view module, u32 nib); @@ -121,6 +121,7 @@ u32 GetNibByName(std::string_view module, std::string_view function); void RegisterHLEModule(std::string_view name, int numFunctions, const HLEFunction *funcTable); int GetNumRegisteredHLEModules(); const HLEModule *GetHLEModuleByIndex(int index); +DisableHLEFlags AlwaysDisableHLEFlags(); // Run the current thread's callbacks after the syscall finishes. void hleCheckCurrentCallbacks(); diff --git a/Core/HLE/sceAudiocodec.cpp b/Core/HLE/sceAudiocodec.cpp index 78e0bd2d66..baf8745f44 100644 --- a/Core/HLE/sceAudiocodec.cpp +++ b/Core/HLE/sceAudiocodec.cpp @@ -49,33 +49,26 @@ static_assert(sizeof(SceAudiocodecCodec) == 128); // // Known byte values. -void CalculateInputBytesAndChannels(const SceAudiocodecCodec *ctx, int codec, int *inputBytes, int *channels) { +void CalculateInputBytesAndChannelsAt3Plus(const SceAudiocodecCodec *ctx, int *inputBytes, int *channels) { *inputBytes = 0; *channels = 2; - switch (codec) { - case PSP_CODEC_AT3PLUS: - { - int size = ctx->unk41 * 8 + 8; - // No idea if this is accurate, this is just a guess... - if (ctx->unk40 & 8) { - *channels = 2; - } else { - *channels = 1; - } - switch (size) { - case 0x118: - case 0x178: - case 0x230: - case 0x2E8: - // These have been seen before, let's return it. - *inputBytes = size; - return; - default: - break; - } + + int size = ctx->unk41 * 8 + 8; + // No idea if this is accurate, this is just a guess... + if (ctx->unk40 & 8) { + *channels = 2; + } else { + *channels = 1; } + switch (size) { + case 0x118: + case 0x178: + case 0x230: + case 0x2E8: + // These have been seen before, let's return it. + *inputBytes = size; + return; default: - // Unsupported codec, ignore. break; } } @@ -118,29 +111,39 @@ void __AudioCodecShutdown() { // TODO: Actually support mono output. static int __AudioCodecInitCommon(u32 ctxPtr, int codec, bool mono) { - PSPAudioType audioType = (PSPAudioType)codec; + const PSPAudioType audioType = (PSPAudioType)codec; if (!IsValidCodec(audioType)) { return hleLogError(Log::ME, SCE_KERNEL_ERROR_OUT_OF_RANGE, "Invalid codec"); } + if (removeDecoder(ctxPtr)) { + WARN_LOG_REPORT(Log::HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec); + } + // Initialize the codec memory. auto ctx = PSPPointer::Create(ctxPtr); ctx->unk_init = 0x5100601; // Firmware version indicator? ctx->err = 0; - if (codec == 0x1002) { + int inFrameBytes = 0; + int channels = 2; + + // Special actions for some codecs. + switch (audioType) { + case PSP_CODEC_MP3: ctx->mp3_9999 = 9999; + break; + case PSP_CODEC_AAC: + // AAC / mp4 + // offsets 40-42 are a 24-bit LE number specifying the sample rate. It's 32000, 44100 or 48000. + // neededMem has been set to 0x18f20. + break; + case PSP_CODEC_AT3PLUS: + CalculateInputBytesAndChannelsAt3Plus(ctx, &inFrameBytes, &channels); + break; } // Create audio decoder for given audio codec and push it into AudioList - if (removeDecoder(ctxPtr)) { - WARN_LOG_REPORT(Log::HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec); - } - - int inFrameBytes; - int channels; - CalculateInputBytesAndChannels(ctx, codec, &inFrameBytes, &channels); - if (inFrameBytes) { INFO_LOG(Log::ME, "sceAudioDecoder: Creating codec with %04x frame size and %d channels, codec %04x", inFrameBytes, channels, codec); AudioDecoder *decoder = CreateAudioDecoder(audioType, 44100, channels, inFrameBytes); @@ -177,7 +180,7 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) { auto ctx = PSPPointer::Create(ctxPtr); // On game-owned heap, no need to allocate. int inFrameBytes; int channels; - CalculateInputBytesAndChannels(ctx, codec, &inFrameBytes, &channels); + CalculateInputBytesAndChannelsAt3Plus(ctx, &inFrameBytes, &channels); // find a decoder in audioList auto decoder = findDecoder(ctxPtr); diff --git a/Core/HLE/sceAudiocodec.h b/Core/HLE/sceAudiocodec.h index 6162ddad0e..681d9066c7 100644 --- a/Core/HLE/sceAudiocodec.h +++ b/Core/HLE/sceAudiocodec.h @@ -26,7 +26,7 @@ enum PSPAudioType { PSP_CODEC_AT3PLUS = 0x00001000, PSP_CODEC_AT3 = 0x00001001, PSP_CODEC_MP3 = 0x00001002, - PSP_CODEC_AAC = 0x00001003, + PSP_CODEC_AAC = 0x00001003, // sceMp4 decodes this in an mp4 container PSP_CODEC_WMA = 0x00001005, }; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 9a7b596a48..ca2af1391e 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1058,7 +1058,7 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load } if (wasDisabled) { - g_OSD.Show(OSDType::MESSAGE_WARNING, StringFromFormat("HLE for %s has been manually disabled", head->modname)); + g_OSD.Show(OSDType::MESSAGE_WARNING, StringFromFormat("HLE for '%s' has been manually disabled", head->modname)); } const u8 *in = ptr; const auto isGzip = head->comp_attribute & 1; diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index b4fba71d93..da59270bad 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -787,9 +787,12 @@ const HLEFunction sceReg[] = { { 0x2D211135, &WrapI_IUI, "sceRegGetKeys", 'i', "ipi" }, { 0xC5768D02, &WrapI_ICUU, "sceRegGetKeyInfoByName", 'i', "isxx" }, { 0x30BE0259, &WrapI_ICUU, "sceRegGetKeyValueByName", 'i', "isxx" }, - // { 0x4CA16893, &WrapI_I, "sceRegRemoveCategory", 'i', "i" }, - // { 0x3615BC87, &WrapI_I, "sceRegRemoveKey", 'i', "i" }, - // { 0x9B25EDF1, &WrapI_I, "sceRegExit", 'i', "i" }, + { 0x4CA16893, &WrapI_IC, "sceRegRemoveCategory", 'i', "i" }, + { 0x3615BC87, nullptr, "sceRegRemoveKey", 'i', "i" }, + { 0x9B25EDF1, nullptr, "sceRegExit", 'i', "i" }, + // TODO: Add test for these. + { 0xBE8C1263, nullptr, "sceRegGetCategoryNumAtRoot", 'i', "ii" }, + { 0x835ECE6F, nullptr, "sceRegGetCategoryListAtRoot", 'i', "ipi" }, }; void Register_sceReg() { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index eca4bce8c8..130f8ab6ca 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1996,11 +1996,16 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new BitCheckBox(&g_Config.iDumpFileTypes, (int)DumpFileType::Atrac3, dev->T("Atrac3/3+"))); list->Add(new ItemHeader("Disable HLE (experimental! Not expected to work yet)")); + for (int i = 0; i < (int)DisableHLEFlags::Count; i++) { DisableHLEFlags flag = (DisableHLEFlags)(1 << i); - const HLEModuleMeta *meta = GetHLEModuleMetaByFlag(flag); - if (meta) { - list->Add(new BitCheckBox(&g_Config.iDisableHLE, (int)flag, meta->modname)); + + // Show a checkbox, unless the setting has graduated to always on. + if (!(flag & AlwaysDisableHLEFlags())) { + const HLEModuleMeta *meta = GetHLEModuleMetaByFlag(flag); + if (meta) { + list->Add(new BitCheckBox(&g_Config.iDisableHLE, (int)flag, meta->modname)); + } } } diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 3774512ef3..b0c6520180 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -1500,7 +1500,7 @@ static void DrawModules(const MIPSDebugInterface *debug, ImConfig &cfg, ImContro ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 170)); } ImGui::Text("%s %d.%d (%s)\n", mod->GetName(), mod->nm.version[1], mod->nm.version[0], mod->isFake ? "FAKE/HLE" : "normal"); - ImGui::Text("Attr: %08x (%s)\n", (mod->nm.attribute & 0x1000) ? "Kernel" : "User"); + ImGui::Text("Attr: %08x (%s)\n", mod->nm.attribute, (mod->nm.attribute & 0x1000) ? "Kernel" : "User"); char buf[512]; mod->GetLongInfo(buf, sizeof(buf)); ImGui::TextUnformatted(buf);