mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-07-11 01:24:28 +02:00
Add shadps4 log + refactor (#4535)
* Log to shadps4.log before game starts * Log update doc * Log critical like before * Log in main file as much as possible
This commit is contained in:
+1
-1
@@ -739,7 +739,7 @@ set(COMMON src/common/logging/classes.h
|
||||
src/common/logging/formatter.h
|
||||
src/common/logging/log.cpp
|
||||
src/common/logging/log.h
|
||||
src/common/logging/thread_name_formatter.h
|
||||
src/common/logging/log_file_sink.h
|
||||
src/common/aes.h
|
||||
src/common/alignment.h
|
||||
src/common/arch.h
|
||||
|
||||
@@ -105,7 +105,7 @@ This section will provide some preliminary steps to take and tips on what to do
|
||||
<summary>When a game crashes and breaks in the debugger</summary>
|
||||
|
||||
1. Analyze the log
|
||||
- A console will open by default when you launch the emulator. It shows the same log messages that go into the log file found at `<emulator executable>/user/log/shad_log.txt`.
|
||||
- A console will open by default when you launch the emulator. It shows the same log messages that go into the log files found at `<emulator executable>/user/log/{shadps4.log, shad_log.txt, {GAME ID}.log}`.
|
||||
|
||||
- It is recommended that you start analyzing the log bottom-up first:
|
||||
- Are there any critical or error-level messages at the end of the log that would point to a reason for the game crashing?
|
||||
@@ -114,6 +114,8 @@ This section will provide some preliminary steps to take and tips on what to do
|
||||
|
||||
- Continue analyzing the log from the start to see other errors (such as with initialization, memory mapping, linker errors etc.)
|
||||
|
||||
- If `shadps4.log` contains error, it should be reported in your issue.
|
||||
|
||||
2. Analyze the stack trace
|
||||
- When the emulator is launched through a debugger, it will **break** when an exception or violation is encountered.\
|
||||
_(**breaking** in this context means pausing execution of the program before it continues or stops altogether.
|
||||
|
||||
@@ -83,7 +83,7 @@ bool KeyManager::LoadFromFile() {
|
||||
|
||||
std::ifstream file(keysPath);
|
||||
if (!file.is_open()) {
|
||||
fmt::println("Could not open key file: {}", keysPath.string());
|
||||
LOG_ERROR(KeyManager, "Could not open key file: {}", keysPath.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ bool KeyManager::LoadFromFile() {
|
||||
return true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error loading keys, using defaults: {}", e.what());
|
||||
LOG_ERROR(KeyManager, "Error loading keys, using defaults: {}", e.what());
|
||||
SetDefaultKeys();
|
||||
return false;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ bool KeyManager::SaveToFile() {
|
||||
|
||||
std::ofstream file(keysPath);
|
||||
if (!file.is_open()) {
|
||||
fmt::println("Could not open key file for writing: {}", keysPath.string());
|
||||
LOG_ERROR(KeyManager, "Could not open key file for writing: {}", keysPath.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -130,13 +130,13 @@ bool KeyManager::SaveToFile() {
|
||||
file.flush();
|
||||
|
||||
if (file.fail()) {
|
||||
fmt::println("Failed to write keys to: {}", keysPath.string());
|
||||
LOG_ERROR(KeyManager, "Failed to write keys to: {}", keysPath.string());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error saving keys: {}", e.what());
|
||||
LOG_ERROR(KeyManager, "Error saving keys: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+88
-62
@@ -5,16 +5,18 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fmt/std.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/thread_name_formatter.h"
|
||||
#include "common/types.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include <spdlog/sinks/async_sink.h>
|
||||
#include <spdlog/sinks/dup_filter_sink.h>
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/logging/log_file_sink.h"
|
||||
#include "common/types.h"
|
||||
#include "core/emulator_settings.h"
|
||||
|
||||
// return codes above 'standard'
|
||||
// https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
||||
enum class ShadPs4ReturnCode : u32 {
|
||||
@@ -27,7 +29,7 @@ namespace Common::Log {
|
||||
bool g_should_append = false;
|
||||
|
||||
static std::shared_ptr<spdlog_stdout> g_console_sink;
|
||||
static std::shared_ptr<spdlog::sinks::basic_file_sink_mt> g_shad_file_sink;
|
||||
static std::shared_ptr<LogFileSink> g_shad_file_sink;
|
||||
|
||||
std::unordered_map<std::string_view, std::shared_ptr<spdlog::logger>> ALL_LOGGERS{
|
||||
{Class::Common, nullptr},
|
||||
@@ -171,16 +173,21 @@ static auto UpdateColorLevels(T sink) {
|
||||
return sink;
|
||||
}
|
||||
|
||||
void Setup(std::string_view log_filename) {
|
||||
static bool already_registered = false;
|
||||
void Setup(std::string_view shadps4_filename) {
|
||||
static std::once_flag already_registered;
|
||||
|
||||
if (!already_registered) {
|
||||
already_registered = true;
|
||||
std::call_once(already_registered, []() {
|
||||
std::atexit(Shutdown);
|
||||
std::at_quick_exit(Flush);
|
||||
std::set_terminate(Terminate);
|
||||
});
|
||||
|
||||
for (auto& [name, logger] : ALL_LOGGERS) {
|
||||
logger = std::make_shared<spdlog::logger>(std::string(name));
|
||||
}
|
||||
|
||||
// Setup console
|
||||
|
||||
#ifdef _WIN32
|
||||
if (EmulatorSettings.GetLogType() == "wincolor") {
|
||||
g_console_sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
|
||||
@@ -192,62 +199,26 @@ void Setup(std::string_view log_filename) {
|
||||
g_console_sink = UpdateColorLevels(std::make_shared<spdlog_stdout>(spdlog::color_mode::always));
|
||||
#endif
|
||||
|
||||
g_console_sink->set_formatter(std::make_unique<thread_name_formatter>(UNLIMITED_SIZE));
|
||||
g_console_sink->set_pattern("%^%v%$");
|
||||
|
||||
g_shad_file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(
|
||||
(GetUserPath(Common::FS::PathType::LogDir) / log_filename).string(), !g_should_append);
|
||||
g_shad_file_sink->set_formatter(
|
||||
std::make_unique<thread_name_formatter>(EmulatorSettings.GetLogSizeLimit()));
|
||||
// Setup file
|
||||
|
||||
std::initializer_list<spdlog::sink_ptr> sinks{g_console_sink, g_shad_file_sink};
|
||||
g_shad_file_sink = std::make_shared<LogFileSink>(
|
||||
(GetUserPath(Common::FS::PathType::LogDir) / shadps4_filename).string(), false,
|
||||
EmulatorSettings.GetLogSizeLimit());
|
||||
g_shad_file_sink->set_pattern("%^%v%$");
|
||||
|
||||
std::initializer_list<spdlog::sink_ptr> async_sink{std::make_shared<spdlog::sinks::async_sink>(
|
||||
spdlog::sinks::async_sink::config{.sinks = sinks})};
|
||||
UpdateSinks();
|
||||
UpdateLogLevels(EmulatorSettings.GetLogFilter());
|
||||
}
|
||||
|
||||
std::initializer_list<spdlog::sink_ptr> dup_filter{
|
||||
std::make_shared<spdlog::sinks::dup_filter_sink_mt>(
|
||||
std::chrono::milliseconds(EmulatorSettings.GetLogMaxSkipDuration()),
|
||||
EmulatorSettings.IsLogSync() ? sinks : async_sink)};
|
||||
void Switch(std::string_view game_filename) {
|
||||
UpdateSinks();
|
||||
UpdateLogLevels(EmulatorSettings.GetLogFilter());
|
||||
|
||||
spdlog::level default_log_level = spdlog::level::info;
|
||||
std::unordered_map<std::string, spdlog::level> log_level_per_class;
|
||||
|
||||
if (EmulatorSettings.IsLogEnable()) {
|
||||
for (const auto class_level : std::views::split(EmulatorSettings.GetLogFilter(), ' ')) {
|
||||
const auto class_level_pair =
|
||||
std::views::split(class_level, ':') | std::ranges::to<std::vector<std::string>>();
|
||||
|
||||
if (class_level_pair.size() != 2) {
|
||||
std::cerr << "bad log filter provided" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (class_level_pair.front()[0] == '*') {
|
||||
default_log_level = spdlog::level_from_str(class_level_pair.back() |
|
||||
std::ranges::to<std::string>());
|
||||
} else {
|
||||
log_level_per_class[class_level_pair.front() | std::ranges::to<std::string>()] =
|
||||
spdlog::level_from_str(class_level_pair.back() |
|
||||
std::ranges::to<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [name, logger] : ALL_LOGGERS) {
|
||||
logger = std::make_shared<spdlog::logger>(
|
||||
std::string(name), EmulatorSettings.IsLogSkipDuplicate()
|
||||
? dup_filter
|
||||
: (EmulatorSettings.IsLogSync() ? sinks : async_sink));
|
||||
|
||||
if (EmulatorSettings.IsLogEnable()) {
|
||||
const auto level_it = log_level_per_class.find(std::string(name));
|
||||
|
||||
logger->set_level(level_it != log_level_per_class.end() ? level_it->second
|
||||
: default_log_level);
|
||||
} else {
|
||||
logger->set_level(spdlog::level::off);
|
||||
}
|
||||
}
|
||||
g_shad_file_sink->_size_limit = EmulatorSettings.GetLogSizeLimit();
|
||||
g_shad_file_sink->session_file_helper_.open(
|
||||
(GetUserPath(Common::FS::PathType::LogDir) / game_filename).string(), !g_should_append);
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
@@ -288,4 +259,59 @@ void Terminate() {
|
||||
std::quick_exit(std::to_underlying(ShadPs4ReturnCode::TERMINATE_WITH_UNKNOWN_EXCEPTION));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateSinks() {
|
||||
std::initializer_list<spdlog::sink_ptr> sinks{g_console_sink, g_shad_file_sink};
|
||||
|
||||
std::initializer_list<spdlog::sink_ptr> async_sink{std::make_shared<spdlog::sinks::async_sink>(
|
||||
spdlog::sinks::async_sink::config{.sinks = sinks})};
|
||||
|
||||
std::initializer_list<spdlog::sink_ptr> dup_filter{
|
||||
std::make_shared<spdlog::sinks::dup_filter_sink_mt>(
|
||||
std::chrono::milliseconds(EmulatorSettings.GetLogMaxSkipDuration()),
|
||||
EmulatorSettings.IsLogSync() ? sinks : async_sink)};
|
||||
|
||||
for (auto& [name, logger] : ALL_LOGGERS) {
|
||||
logger->sinks() = EmulatorSettings.IsLogSkipDuplicate()
|
||||
? dup_filter
|
||||
: (EmulatorSettings.IsLogSync() ? sinks : async_sink);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateLogLevels(std::string_view log_filter) {
|
||||
spdlog::level default_log_level = spdlog::level::info;
|
||||
std::unordered_map<std::string, spdlog::level> log_level_per_class;
|
||||
|
||||
if (EmulatorSettings.IsLogEnable()) {
|
||||
for (const auto class_level : std::views::split(log_filter, ' ')) {
|
||||
const auto class_level_pair =
|
||||
std::views::split(class_level, ':') | std::ranges::to<std::vector<std::string>>();
|
||||
|
||||
if (class_level_pair.size() != 2) {
|
||||
LOG_ERROR(Config, "bad log filter provided");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (class_level_pair.front()[0] == '*') {
|
||||
default_log_level = spdlog::level_from_str(class_level_pair.back() |
|
||||
std::ranges::to<std::string>());
|
||||
} else {
|
||||
log_level_per_class[class_level_pair.front() | std::ranges::to<std::string>()] =
|
||||
spdlog::level_from_str(class_level_pair.back() |
|
||||
std::ranges::to<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [name, logger] : ALL_LOGGERS) {
|
||||
if (EmulatorSettings.IsLogEnable()) {
|
||||
const auto level_it = log_level_per_class.find(std::string(name));
|
||||
|
||||
logger->set_level(level_it != log_level_per_class.end() ? level_it->second
|
||||
: default_log_level);
|
||||
} else {
|
||||
logger->set_level(spdlog::level::off);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -7,10 +7,7 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <spdlog/details/fmt_helper.h>
|
||||
#include <spdlog/sinks/async_sink.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
#include <spdlog/sinks/dup_filter_sink.h>
|
||||
#include <spdlog/sinks/null_sink.h>
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -30,7 +27,9 @@ namespace Common::Log {
|
||||
extern bool g_should_append;
|
||||
extern std::unordered_map<std::string_view, std::shared_ptr<spdlog::logger>> ALL_LOGGERS;
|
||||
|
||||
void Setup(std::string_view log_filename);
|
||||
void Setup(std::string_view shadps4_filename);
|
||||
|
||||
void Switch(std::string_view game_filename);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
@@ -38,6 +37,10 @@ void Flush();
|
||||
|
||||
void Terminate();
|
||||
|
||||
void UpdateSinks();
|
||||
|
||||
void UpdateLogLevels(std::string_view log_filter);
|
||||
|
||||
static constexpr std::array level_string_views{"Trace", "Debug", "Info", "Warning",
|
||||
"Error", "Critical", "Off"};
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/formatter.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
namespace Common::Log {
|
||||
static constexpr unsigned long long UNLIMITED_SIZE = 0;
|
||||
|
||||
/*
|
||||
* Trivial file sink with two files as target : main and session
|
||||
*/
|
||||
class LogFileSink final : public spdlog::sinks::base_sink<std::mutex> {
|
||||
public:
|
||||
explicit LogFileSink(const spdlog::filename_t& main_filename, bool truncate = false,
|
||||
unsigned long long size_limit = UNLIMITED_SIZE)
|
||||
: _size_limit{size_limit} {
|
||||
main_file_helper_.open(main_filename, truncate);
|
||||
}
|
||||
|
||||
spdlog::details::file_helper main_file_helper_;
|
||||
spdlog::details::file_helper session_file_helper_;
|
||||
|
||||
unsigned long long _size_limit;
|
||||
|
||||
protected:
|
||||
void sink_it_(const spdlog::details::log_msg& msg) override {
|
||||
spdlog::memory_buf_t formatted;
|
||||
this->formatter_->format(msg, formatted);
|
||||
|
||||
if (session_file_helper_.filename().empty()) {
|
||||
// always log in the main file, it shouldnt be too big
|
||||
main_file_helper_.write(formatted);
|
||||
} else if (_current_size < _size_limit || msg.log_level == spdlog::level::critical) {
|
||||
session_file_helper_.write(formatted);
|
||||
_current_size += formatted.size();
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override {
|
||||
main_file_helper_.flush();
|
||||
session_file_helper_.flush();
|
||||
}
|
||||
|
||||
unsigned long long _current_size = 0;
|
||||
};
|
||||
} // namespace Common::Log
|
||||
@@ -1,42 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/formatter.h>
|
||||
|
||||
namespace Common::Log {
|
||||
static constexpr unsigned long long UNLIMITED_SIZE = 0;
|
||||
|
||||
struct thread_name_formatter : spdlog::formatter {
|
||||
~thread_name_formatter() override = default;
|
||||
|
||||
thread_name_formatter(unsigned long long size_limit) : _size_limit(size_limit) {}
|
||||
|
||||
void format(const spdlog::details::log_msg& msg, spdlog::memory_buf_t& dest) override {
|
||||
if (_size_limit != UNLIMITED_SIZE && _current_size >= _size_limit) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.color_range_start = dest.size();
|
||||
|
||||
spdlog::details::fmt_helper::append_string_view(msg.payload, dest);
|
||||
spdlog::details::fmt_helper::append_string_view(spdlog::details::os::default_eol, dest);
|
||||
|
||||
msg.color_range_end = dest.size();
|
||||
|
||||
_current_size += dest.size();
|
||||
}
|
||||
|
||||
std::unique_ptr<formatter> clone() const override {
|
||||
return std::make_unique<thread_name_formatter>(_size_limit);
|
||||
}
|
||||
|
||||
const unsigned long long _size_limit;
|
||||
unsigned long long _current_size = 0;
|
||||
};
|
||||
} // namespace Common::Log
|
||||
@@ -91,9 +91,9 @@ void EmulatorSettingsImpl::PrintChangedSummary(const std::vector<std::string>& c
|
||||
if (changed.empty()) {
|
||||
return;
|
||||
}
|
||||
fmt::println("Game-specific overrides applied:");
|
||||
LOG_DEBUG(Config, "Game-specific overrides applied:");
|
||||
for (const auto& k : changed)
|
||||
fmt::println(" * {}", k);
|
||||
LOG_DEBUG(Config, " * {}", k);
|
||||
}
|
||||
|
||||
// ── Singleton ────────────────────────────────────────────────────────
|
||||
@@ -258,7 +258,7 @@ void EmulatorSettingsImpl::ResetGameSpecificValue(const std::string& key) {
|
||||
return;
|
||||
if (tryGroup(m_vulkan))
|
||||
return;
|
||||
fmt::println("ResetGameSpecificValue: key '{}' not found", key);
|
||||
LOG_DEBUG(Config, "ResetGameSpecificValue: key '{}' not found", key);
|
||||
}
|
||||
|
||||
bool EmulatorSettingsImpl::Save(const std::string& serial) {
|
||||
@@ -300,7 +300,7 @@ bool EmulatorSettingsImpl::Save(const std::string& serial) {
|
||||
|
||||
std::ofstream out(path);
|
||||
if (!out) {
|
||||
fmt::println("Failed to open game config for writing: {}", path.string());
|
||||
LOG_DEBUG(Config, "Failed to open game config for writing: {}", path.string());
|
||||
return false;
|
||||
}
|
||||
out << std::setw(2) << j;
|
||||
@@ -342,14 +342,14 @@ bool EmulatorSettingsImpl::Save(const std::string& serial) {
|
||||
|
||||
std::ofstream out(path);
|
||||
if (!out) {
|
||||
fmt::println("Failed to open config for writing: {}", path.string());
|
||||
LOG_DEBUG(Config, "Failed to open config for writing: {}", path.string());
|
||||
return false;
|
||||
}
|
||||
out << std::setw(2) << existing;
|
||||
return !out.fail();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error saving settings: {}", e.what());
|
||||
LOG_DEBUG(Config, "Error saving settings: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -469,7 +469,7 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
|
||||
return true;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error loading settings: {}", e.what());
|
||||
LOG_DEBUG(Config, "Error loading settings: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -669,7 +669,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
|
||||
}
|
||||
s.install_dirs.value = settings_install_dirs;
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Failed to transfer install directories: {}", e.what());
|
||||
LOG_DEBUG(Config, "Failed to transfer install directories: {}", e.what());
|
||||
}
|
||||
|
||||
// Transfer addon install directory
|
||||
@@ -685,7 +685,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Failed to transfer addon install directory: {}", e.what());
|
||||
LOG_DEBUG(Config, "Failed to transfer addon install directory: {}", e.what());
|
||||
}
|
||||
}
|
||||
if (og_data.contains("General")) {
|
||||
@@ -704,7 +704,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Failed to transfer sysmodules install directory: {}", e.what());
|
||||
LOG_DEBUG(Config, "Failed to transfer sysmodules install directory: {}", e.what());
|
||||
}
|
||||
|
||||
// Transfer font install directory
|
||||
@@ -720,7 +720,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Failed to transfer font install directory: {}", e.what());
|
||||
LOG_DEBUG(Config, "Failed to transfer font install directory: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,9 +127,9 @@ inline OverrideItem make_override(const char* key, Setting<T> Struct::* member)
|
||||
}
|
||||
dst.game_specific_value = newValue;
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("[make_override] error parsing {}: {}", key, e.what());
|
||||
fmt::println("[make_override] Entry was: {}", entry.dump());
|
||||
fmt::println("[make_override] Type name: {}", entry.type_name());
|
||||
LOG_DEBUG(Config, "[make_override] error parsing {}: {}", key, e.what());
|
||||
LOG_DEBUG(Config, "[make_override] Entry was: {}", entry.dump());
|
||||
LOG_DEBUG(Config, "[make_override] Type name: {}", entry.type_name());
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -59,13 +59,13 @@ bool UserSettingsImpl::Save() const {
|
||||
|
||||
std::ofstream out(path);
|
||||
if (!out) {
|
||||
fmt::println("Failed to open user settings for writing: {}", path.string());
|
||||
LOG_DEBUG(Config, "Failed to open user settings for writing: {}", path.string());
|
||||
return false;
|
||||
}
|
||||
out << std::setw(2) << existing;
|
||||
return !out.fail();
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error saving user settings: {}", e.what());
|
||||
LOG_DEBUG(Config, "Error saving user settings: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ bool UserSettingsImpl::Load() {
|
||||
|
||||
std::ifstream in(path);
|
||||
if (!in) {
|
||||
fmt::println("Failed to open user settings: {}", path.string());
|
||||
LOG_DEBUG(Config, "Failed to open user settings: {}", path.string());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ bool UserSettingsImpl::Load() {
|
||||
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
fmt::println("Error loading user settings: {}", e.what());
|
||||
LOG_DEBUG(Config, "Error loading user settings: {}", e.what());
|
||||
if (m_userManager.GetUsers().user.empty())
|
||||
m_userManager.GetUsers() = m_userManager.CreateDefaultUsers();
|
||||
return false;
|
||||
|
||||
+3
-3
@@ -275,10 +275,10 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize logging as soon as possible
|
||||
EmulatorSettings.Load(id);
|
||||
Common::Log::Setup((!id.empty() && EmulatorSettings.IsLogSeparate()) ? id + ".log"
|
||||
: "shad_log.txt");
|
||||
// Switch to configured log
|
||||
Common::Log::Switch((!id.empty() && EmulatorSettings.IsLogSeparate()) ? id + ".log"
|
||||
: "shad_log.txt");
|
||||
|
||||
auto guest_eboot_path = "/app0/" + eboot_name.generic_string();
|
||||
const auto eboot_path = mnt->GetHostPath(guest_eboot_path);
|
||||
|
||||
@@ -115,18 +115,18 @@ SDL_Texture* LoadSdlTextureData(std::vector<u8> data) {
|
||||
unsigned char* image_data = stbi_load_from_memory(
|
||||
(const unsigned char*)data.data(), (int)data.size(), &image_width, &image_height, NULL, 4);
|
||||
if (image_data == nullptr) {
|
||||
fmt::println("Failed to load image: {}", stbi_failure_reason());
|
||||
LOG_ERROR(ImGui, "Failed to load image: {}", stbi_failure_reason());
|
||||
}
|
||||
|
||||
SDL_Surface* surface = SDL_CreateSurfaceFrom(image_width, image_height, SDL_PIXELFORMAT_RGBA32,
|
||||
(void*)image_data, channels * image_width);
|
||||
if (surface == nullptr) {
|
||||
fmt::println("Unable to create SDL surface: {}", SDL_GetError());
|
||||
LOG_ERROR(ImGui, "Unable to create SDL surface: {}", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
if (texture == nullptr) {
|
||||
fmt::println("Unable to create SDL texture: {}", SDL_GetError());
|
||||
LOG_ERROR(ImGui, "Unable to create SDL texture: {}", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_DestroySurface(surface);
|
||||
@@ -190,13 +190,13 @@ void GetGameIconInfo(std::vector<IconInfo>& icons) {
|
||||
|
||||
void Launch(char* executableName) {
|
||||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
fmt::println("SDL_INIT_VIDEO Error: {}", SDL_GetError());
|
||||
LOG_ERROR(ImGui, "SDL_INIT_VIDEO Error: {}", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SDL_Init(SDL_INIT_GAMEPAD)) {
|
||||
fmt::println("SDL_INIT_GAMEPAD Error: {}", SDL_GetError());
|
||||
LOG_ERROR(ImGui, "SDL_INIT_GAMEPAD Error: {}", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_Window* window =
|
||||
@@ -204,7 +204,7 @@ void Launch(char* executableName) {
|
||||
renderer = SDL_CreateRenderer(window, nullptr);
|
||||
|
||||
if (window == nullptr) {
|
||||
fmt::println("SDL Window Creation Error: {}", SDL_GetError());
|
||||
LOG_ERROR(ImGui, "SDL Window Creation Error: {}", SDL_GetError());
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_Quit();
|
||||
return;
|
||||
|
||||
+11
-6
@@ -103,6 +103,11 @@ int main(int argc, char* argv[]) {
|
||||
if (waitPid)
|
||||
Core::Debugger::WaitForPid(*waitPid);
|
||||
|
||||
// Initialize main log with default config
|
||||
Common::Log::Setup("shadps4.log");
|
||||
|
||||
LOG_INFO(Debug, "Run: {}", std::span(argv, argc));
|
||||
|
||||
IPC::Instance().Init();
|
||||
|
||||
auto emu_state = std::make_shared<EmulatorState>();
|
||||
@@ -130,14 +135,14 @@ int main(int argc, char* argv[]) {
|
||||
if (addGameFolder) {
|
||||
EmulatorSettings.AddGameInstallDir(*addGameFolder);
|
||||
EmulatorSettings.Save();
|
||||
std::cout << "Game folder successfully saved.\n";
|
||||
LOG_INFO(Config, "Game folder successfully saved.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setAddonFolder) {
|
||||
EmulatorSettings.SetAddonInstallDir(*setAddonFolder);
|
||||
EmulatorSettings.Save();
|
||||
std::cout << "Addon folder successfully saved.\n";
|
||||
LOG_INFO(Config, "Addon folder successfully saved.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -146,7 +151,7 @@ int main(int argc, char* argv[]) {
|
||||
gamePath = gameArgs.front();
|
||||
gameArgs.erase(gameArgs.begin());
|
||||
} else {
|
||||
std::cerr << "Error: Please provide a game path or ID.\n";
|
||||
LOG_ERROR(Debug, "Please provide a game path or ID.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -154,7 +159,7 @@ int main(int argc, char* argv[]) {
|
||||
if (gameArgs.front() == "--") {
|
||||
gameArgs.erase(gameArgs.begin());
|
||||
} else {
|
||||
std::cerr << "Error: unhandled flags\n";
|
||||
LOG_ERROR(Debug, "unhandled flags");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -172,7 +177,7 @@ int main(int argc, char* argv[]) {
|
||||
} else if (*fullscreenStr == "false") {
|
||||
EmulatorSettings.SetFullScreen(false);
|
||||
} else {
|
||||
std::cerr << "Error: Invalid argument for --fullscreen (use true|false)\n";
|
||||
LOG_ERROR(Debug, "Invalid argument for --fullscreen (use true|false)");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -199,7 +204,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
std::cerr << "Error: Game ID or file path not found: " << *gamePath << "\n";
|
||||
LOG_ERROR(Debug, "Game ID or file path not found: {}", *gamePath);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user