| 374 | } |
| 375 | |
| 376 | extern void dump_executable(std::span<const u8> data, const ppu_module<lv2_obj>* _module, std::string_view title_id) |
| 377 | { |
| 378 | std::string_view filename = _module->path; |
| 379 | filename = filename.substr(filename.find_last_of('/') + 1); |
| 380 | |
| 381 | const std::string lower = fmt::to_lower(filename); |
| 382 | |
| 383 | // Format filename and directory name |
| 384 | // Make each directory for each file so tools like IDA can work on it cleanly |
| 385 | const std::string dir_path = fs::get_cache_dir() + "ppu_progs/" + std::string{!title_id.empty() ? title_id : "untitled"} + fmt::format("-%s-%s", fmt::base57(_module->sha1), filename) + '/'; |
| 386 | const std::string file_path = dir_path + (lower.ends_with(".prx") || lower.ends_with(".sprx") ? "prog.prx" : "exec.elf"); |
| 387 | |
| 388 | if (fs::create_dir(dir_path) || fs::g_tls_error == fs::error::exist) |
| 389 | { |
| 390 | if (fs::file out{file_path, fs::create + fs::write}) |
| 391 | { |
| 392 | if (out.size() == data.size()) |
| 393 | { |
| 394 | // Risky optimization: assume if file size match they are equal and does not need to rewrite it |
| 395 | // But it is a debug option and if there are problems the user/developer can remove the previous file |
| 396 | } |
| 397 | else |
| 398 | { |
| 399 | out.trunc(0); |
| 400 | out.write(data.data(), data.size()); |
| 401 | } |
| 402 | } |
| 403 | else |
| 404 | { |
| 405 | sys_log.error("Failed to save decrypted executable of \"%s\": Failure to create file \"%s\" (%s)", Emu.GetBoot(), filename, fs::g_tls_error); |
| 406 | } |
| 407 | } |
| 408 | else |
| 409 | { |
| 410 | sys_log.error("Failed to save decrypted executable of \"%s\": Failure to create directory \"%s\" (%s)", Emu.GetBoot(), dir_path, fs::g_tls_error); |
| 411 | } |
| 412 | } |
| 413 | |
| 414 | void Emulator::Init() |
| 415 | { |