diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 0cc02ecf0b..d0612e61a0 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -710,7 +710,7 @@ bool CreateDir(const Path &path) { // Creates the full path of fullPath returns true on success bool CreateFullPath(const Path &path) { if (File::Exists(path)) { - DEBUG_LOG(Log::IO, "CreateFullPath: path exists %s", path.ToVisualString().c_str()); + VERBOSE_LOG(Log::IO, "CreateFullPath: path exists %s", path.ToVisualString().c_str()); return true; } diff --git a/Common/Log/LogManager.cpp b/Common/Log/LogManager.cpp index f07fb838fb..fc1cdab996 100644 --- a/Common/Log/LogManager.cpp +++ b/Common/Log/LogManager.cpp @@ -27,7 +27,6 @@ #include #include "Common/Data/Encoding/Utf8.h" - #include "Common/Log/LogManager.h" #if PPSSPP_PLATFORM(WINDOWS) @@ -469,25 +468,27 @@ void LogManager::StdioLog(const LogMessage &message) { } void PrintfLog(const LogMessage &message) { + const char *category = message.log; + switch (message.level) { case LogLevel::LVERBOSE: - fprintf(stderr, "V %s", message.msg.c_str()); + fprintf(stderr, "V %s: %s", category, message.msg.c_str()); break; case LogLevel::LDEBUG: - fprintf(stderr, "D %s", message.msg.c_str()); + fprintf(stderr, "D %s: %s", category, message.msg.c_str()); break; case LogLevel::LINFO: - fprintf(stderr, "I %s", message.msg.c_str()); + fprintf(stderr, "I %s: %s", category, message.msg.c_str()); break; case LogLevel::LERROR: - fprintf(stderr, "E %s", message.msg.c_str()); + fprintf(stderr, "E %s: %s", category, message.msg.c_str()); break; case LogLevel::LWARNING: - fprintf(stderr, "W %s", message.msg.c_str()); + fprintf(stderr, "W %s: %s", category, message.msg.c_str()); break; case LogLevel::LNOTICE: default: - fprintf(stderr, "N %s", message.msg.c_str()); + fprintf(stderr, "N %s: %s", category, message.msg.c_str()); break; } } diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp index 32ea4096c1..50a2f9c99d 100644 --- a/Core/CmdLine.cpp +++ b/Core/CmdLine.cpp @@ -151,6 +151,7 @@ static const CommandLineParam g_autoParams[] = { {POFF(timeout), CmdParamType::Double, "timeout", '\0', "Set the timeout value"}, {POFF(resolutionScale), CmdParamType::Int, "resolution-scale", '\0', "Set the resolution scale factor"}, {POFF(debuggerPort), CmdParamType::Int, "debugger", '\0', "Enable the WebSocket debugger on this port (0 = pick automatically); see docs/WebSocketDebugger.md"}, + {POFF(bootVSH), CmdParamType::Bool, "vsh", '\0', "Boot the VSH (requires files dumped from a PSP in the flash0 directory)"}, // TODO: At some point we should maybe simply expose all config settings to be set directly from the command line automatically? }; @@ -422,6 +423,8 @@ void CommandLineOptions::ApplyToConfig() const { g_Config.DoNotSaveSetting(&g_Config.iInternalResolution); } + // --vsh is applied by the caller. + // Note: dpi is not applied here - it's platform-specific. // Platforms should check cmdLineOptions.dpi.has_value() and handle accordingly. } diff --git a/Core/CmdLine.h b/Core/CmdLine.h index 0724610419..2b045fc865 100644 --- a/Core/CmdLine.h +++ b/Core/CmdLine.h @@ -44,6 +44,10 @@ struct CommandLineOptions { // Also breaks the CPU at start in the headless build. See docs/WebSocketDebugger.md. std::optional debuggerPort; + // Attempts to boot the vsh, which will only work if the correct files are present in the flash + // and once we've fixed all the bugs. This is just here to allow testing. + std::optional bootVSH; + std::optional appendConfig; std::optional root; // mount root, needs more explanation std::optional stateToLoad; diff --git a/Core/Core.cpp b/Core/Core.cpp index 5cfcfdc92f..ce5bc45e2d 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -625,7 +625,7 @@ void Core_ExecException(u32 address, u32 pc, ExecExceptionType type) { } void Core_BreakException(u32 pc) { - ERROR_LOG(Log::CPU, "BREAK!"); + ERROR_LOG(Log::CPU, "CPU exception: break instruction hit at %08x", pc); MIPSExceptionInfo &e = g_exceptionInfo; e = {}; diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index e4fd7e2bf8..658d668b18 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -362,7 +362,7 @@ void ElfReader::LoadRelocations2(int rel_seg) } op = Memory::Read_Instruction(rel_offset, true).encoding; - DEBUG_LOG(Log::Loader, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op); + VERBOSE_LOG(Log::Loader, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op); switch(type){ case 0: diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 3534e301cd..ed98a9b851 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -68,18 +68,23 @@ DirectoryFileSystem::DirectoryFileSystem(IHandleAllocator *_hAlloc, const Path & static const std::string_view mixedCase = "wJpCzSBNnZfxSgoS"; static const std::string_view upperCase = "WJPCZSBNNZFXSGOS"; - // Check for case sensitivity - bool checkSucceeded = false; - File::CreateEmptyFile(basePath / mixedCase); - if (File::Exists(basePath / mixedCase)) { - checkSucceeded = true; - if (!File::Exists(basePath / upperCase)) { - flags |= FileSystemFlags::CASE_SENSITIVE; + // Check for case sensitivity. TODO: Add more special cases to avoid the file creation dance. +#if !PPSSPP_PLATFORM(WINDOWS) + if (basePath.Type() == PathType::CONTENT_URI) { + // Android: Is not case sensitive. + } else { + bool checkSucceeded = false; + File::CreateEmptyFile(basePath / mixedCase); + if (File::Exists(basePath / mixedCase)) { + checkSucceeded = true; + if (!File::Exists(basePath / upperCase)) { + flags |= FileSystemFlags::CASE_SENSITIVE; + } } + File::Delete(basePath / mixedCase); + INFO_LOG(Log::IO, "Is file system case sensitive? %s (base: '%s') (checkOK: %d)", (flags & FileSystemFlags::CASE_SENSITIVE) ? "yes" : "no", _basePath.c_str(), checkSucceeded); } - File::Delete(basePath / mixedCase); - - INFO_LOG(Log::IO, "Is file system case sensitive? %s (base: '%s') (checkOK: %d)", (flags & FileSystemFlags::CASE_SENSITIVE) ? "yes" : "no", _basePath.c_str(), checkSucceeded); +#endif hAlloc = _hAlloc; } diff --git a/Core/HLE/sceReg.cpp b/Core/HLE/sceReg.cpp index 2d51cf1d9d..8eb36ee349 100644 --- a/Core/HLE/sceReg.cpp +++ b/Core/HLE/sceReg.cpp @@ -57,9 +57,9 @@ struct KeyValue { const KeyValue *dirContents; // intValue is the count. }; - // TODO: /DATA/FONT/PROPERTY could just be generated from our fontRegistry in sceFont.cpp. -// Dump of the PSP registry using tests/misc/reg.prx in pspautotests + +// Partial dump of the PSP registry using tests/misc/reg.prx in pspautotests // Dump of /DATA/FONT/PROPERTY/INFO0 static const KeyValue tree_DATA_FONT_PROPERTY_INFO0[] = { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 442fea7ba9..964d6ef215 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -579,11 +579,13 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO // Apply parsed command line options to config. cmdLineOptions.ApplyToConfig(); - const char *fileToLog = nullptr; - bool gotBootFilename = false; boot_filename.clear(); + if (boot_filename.empty() && cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { + boot_filename = g_Config.flash0Directory / "vsh/module/vshmain.prx"; + } + // Parse command line LogLevel logLevel = LogLevel::LINFO; bool forceLogLevel = false; @@ -596,6 +598,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO setLogLevel(cmdLineOptions.logLevel.value()); } + std::string fileToLog; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { #if defined(__APPLE__) @@ -672,7 +675,7 @@ void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineO } } - if (fileToLog) { + if (!fileToLog.empty()) { // Start logging immediately. g_logManager.EnableOutput(LogOutput::File); g_logManager.SetFileLogPath(Path(fileToLog)); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index b35e9915b7..ab29ab0c3d 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -510,11 +510,14 @@ int main(int argc, const char* argv[]) { } } + if (!fullLog) { + printf("Pass the -l flag to see full log output.\n"); + } + for (const std::string &filename : cmdLineOptions.bootFilenames) { AddToTestsByPath(&testFilenames, filename); } - if (testFilenames.size() == 1 && testFilenames[0][0] == '@') testFilenames = ReadFromListFile(testFilenames[0].substr(1)); @@ -528,23 +531,20 @@ int main(int argc, const char* argv[]) { testFilenames.end() ); - if (testFilenames.empty()) - return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); - g_Config.bEnableLogging = (fullLog || outputDebugStringLog); g_logManager.Init(&g_Config.bEnableLogging, outputDebugStringLog); for (int i = 0; i < (int)Log::NUMBER_OF_LOGS; i++) { Log type = (Log)i; g_logManager.SetEnabled(type, (fullLog || outputDebugStringLog)); - g_logManager.SetLogLevel(type, LogLevel::LDEBUG); + g_logManager.SetLogLevel(type, LogLevel::LDEBUG); // TODO: Make the level configurable. } if (fullLog) { // Only with --log, add the printfLogger. g_logManager.EnableOutput(LogOutput::Printf); } - g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS | RestoreSettingsBits::CONTROLS | RestoreSettingsBits::RECENT, true); + g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS | RestoreSettingsBits::CONTROLS | RestoreSettingsBits::RECENT, false); // Needs to be after log so we don't interfere with test output. g_threadManager.Init(cpu_info.num_cores, cpu_info.logical_cpu_count); @@ -679,6 +679,13 @@ int main(int argc, const char* argv[]) { UpdateUIState(UISTATE_INGAME); + if (cmdLineOptions.bootVSH.has_value() && cmdLineOptions.bootVSH.value()) { + AddToTestsByPath(&testFilenames, (g_Config.flash0Directory / "vsh/module/vshmain.prx").ToString()); + } + if (testFilenames.empty()) { + return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); + } + if (cmdLineOptions.debuggerPort.has_value()) { coreParameter.startBreak = true; StartWebServer(WebServerFlags::DEBUGGER);