diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 211805cc4d..6df6380485 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -3847,16 +3847,24 @@ void spu_recompiler_base::dump(const spu_program& result, std::string& out) fmt::append(hash, "%s", fmt::base57(output)); } - fmt::append(out, "========== SPU BLOCK 0x%05x (size %u, %s) ==========\n", result.entry_point, result.data.size(), hash); + fmt::append(out, "========== SPU BLOCK 0x%05x (size %u, %s) ==========\n\n", result.entry_point, result.data.size(), hash); for (auto& bb : m_bbs) { for (u32 pos = bb.first, end = bb.first + bb.second.size * 4; pos < end; pos += 4) { dis_asm.disasm(pos); - fmt::append(out, ">%s\n", dis_asm.last_opcode); + + if (!dis_asm.last_opcode.ends_with('\n')) + { + dis_asm.last_opcode += '\n'; + } + + fmt::append(out, ">%s", dis_asm.last_opcode); } + out += '\n'; + if (m_block_info[bb.first / 4]) { fmt::append(out, "A: [0x%05x] %s\n", bb.first, m_entry_info[bb.first / 4] ? (m_ret_info[bb.first / 4] ? "Chunk" : "Entry") : "Block"); @@ -5823,7 +5831,7 @@ public: if (g_cfg.core.spu_debug) { out.flush(); - fs::file(m_spurt->get_cache_path() + "spu-ir.log", fs::write + fs::append).write(log); + fs::write_file(m_spurt->get_cache_path() + "spu-ir.log", fs::create + fs::write + fs::append, log); } #if defined(__APPLE__) @@ -6241,7 +6249,7 @@ public: if (g_cfg.core.spu_debug) { - fs::file(m_spurt->get_cache_path() + "spu-ir.log", fs::write + fs::append).write(log); + fs::write_file(m_spurt->get_cache_path() + "spu-ir.log", fs::create + fs::write + fs::append, log); } fmt::throw_exception("Compilation failed"); @@ -6276,7 +6284,7 @@ public: if (g_cfg.core.spu_debug) { out.flush(); - fs::file(m_spurt->get_cache_path() + "spu-ir.log", fs::write + fs::append).write(log); + fs::write_file(m_spurt->get_cache_path() + "spu-ir.log", fs::create + fs::write + fs::append, log); } return spu_runtime::g_interpreter; @@ -11243,7 +11251,7 @@ struct spu_fast : public spu_recompiler_base { std::string log; this->dump(func, log); - fs::file(m_spurt->get_cache_path() + "spu.log", fs::write + fs::append).write(log); + fs::write_file(m_spurt->get_cache_path() + "spu.log", fs::create + fs::write + fs::append, log); } // Allocate executable area with necessary size diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 29716a8236..9eff4d8162 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -2899,6 +2899,8 @@ void Emulator::Kill(bool allow_autoexit, bool savestate) // Final termination from main thread (move the last ownership of join thread in order to destroy it) CallFromMainThread([join_thread = std::move(join_thread), allow_autoexit, this]() mutable { + const std::string cache_path = rpcs3::cache::get_ppu_cache(); + cpu_thread::cleanup(); initialize_timebased_time(0, true); @@ -2959,7 +2961,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate) m_state = system_state::stopped; GetCallbacks().on_stop(); - if (g_tty) + if (g_tty && sys_log.notice) { // Write merged TTY output after emulation has been safely stopped @@ -2973,6 +2975,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate) std::string tty_buffer(std::min(attempted_read_size, c_max_tty_spill_size), '\0'); tty_buffer.resize(tty_read_fd.read_at(m_tty_file_init_pos, tty_buffer.data(), tty_buffer.size())); + tty_read_fd.close(); if (!tty_buffer.empty()) { @@ -2983,6 +2986,39 @@ void Emulator::Kill(bool allow_autoexit, bool savestate) } } + if (g_cfg.core.spu_debug && sys_log.notice) + { + if (fs::file spu_log{cache_path + "/spu.log"}) + { + // 96MB limit, this may be a lot but this only has an effect when enabling the debug option + constexpr usz c_max_tty_spill_size = 0x60'0000; + + std::string log_buffer(std::min(spu_log.size(), c_max_tty_spill_size), '\0'); + log_buffer.resize(spu_log.read(log_buffer.data(), log_buffer.size())); + spu_log.close(); + + if (!log_buffer.empty()) + { + usz to_remove = 0; + usz part_ctr = 1; + + for (std::string_view not_logged = log_buffer; !not_logged.empty(); part_ctr++, not_logged.remove_prefix(to_remove)) + { + std::string_view to_log = not_logged; + to_log = to_log.substr(0, 0x8'0000); + to_log = to_log.substr(0, utils::add_saturate(to_log.rfind("\n========== SPU BLOCK"sv), 1)); + to_remove = to_log.size(); + + // Cannot log it all at once due to technical reasons, split it to 8MB at maximum of whole functions + // Assume the block prefix exists because it is created by RPCS3 (or log it in an ugly manner if it does not exist) + sys_log.notice("Logging spu.log part %u:\n\n%s\n", part_ctr, to_log); + } + + sys_log.notice("End spu.log"); + } + } + } + // Always Enable display sleep, not only if it was prevented. enable_display_sleep();