#include "config.h" #include "sdl_window.h" #include #include #include #include #include #include #include #include #include #include namespace config { bool dump_drc_frames = false; bool dump_tv_frames = false; std::string dump_frames_dir = "frames"; std::string renderer = "vulkan"; } // namespace config std::shared_ptr gCliLog; static excmd::parser getCommandLineParser() { excmd::parser parser; using excmd::description; using excmd::optional; using excmd::default_value; using excmd::allowed; using excmd::value; using excmd::make_default_value; parser.global_options() .add_option("v,version", description { "Show version." }) .add_option("h,help", description { "Show help." }); auto replayOptions = parser.add_option_group("Replay Options") .add_option("dump-drc-frames", description { "Dump rendered DRC frames to file." }) .add_option("dump-tv-frames", description { "Dump rendered TV frames to file." }) .add_option("dump-frames-dir", description { "Folder to place dumped frames in" }, make_default_value(config::dump_frames_dir)) .add_option("renderer", description { "Which graphics renderer to use." }, make_default_value(config::renderer)); parser.add_command("help") .add_argument("help-command", optional {}, value {}); parser.add_command("replay") .add_argument("trace file", value {}) .add_option_group(replayOptions); return parser; } static int replay(const std::string &path) { SDLWindow sdl; if (!sdl.initCore()) { gCliLog->error("Failed to initialise SDL"); return -1; } if (!sdl.initGraphics()) { gCliLog->error("Failed to initialise graphics backend."); return -1; } return sdl.run(path); } int start(excmd::parser &parser, excmd::option_state &options) { // Print version if (options.has("version")) { // TODO: print git hash std::cout << "Decaf PM4 Replay tool version 0.0.1" << std::endl; std::exit(0); } // Print help if (options.empty() || options.has("help")) { if (options.has("help-command")) { std::cout << parser.format_help("decaf-pm4-replay", options.get("help-command")) << std::endl; } else { std::cout << parser.format_help("decaf-pm4-replay") << std::endl; } std::exit(0); } if (!options.has("replay")) { return 0; } if (options.has("dump-drc-frames")) { config::dump_drc_frames = true; } if (options.has("dump-tv-frames")) { config::dump_tv_frames = true; } if (options.has("dump-frames-dir")) { config::dump_frames_dir = options.get("dump-frames-dir"); } if (options.has("renderer")) { config::renderer = options.get("renderer"); } auto traceFile = options.get("trace file"); // Initialise libdecaf logger auto decafSettings = decaf::Settings { }; decafSettings.log.to_file = true; decafSettings.log.to_stdout = true; decafSettings.log.level = "debug"; decaf::setConfig(decafSettings); decaf::initialiseLogging("pm4-replay.txt"); auto gpuSettings = gpu::Settings { }; gpuSettings.debug.debug_enabled = true; gpu::setConfig(gpuSettings); gCliLog = decaf::makeLogger("decaf-pm4-replay"); gCliLog->set_pattern("[%l] %v"); gCliLog->info("Trace path {}", traceFile); // Initialise CPU to setup physical memory cpu::initialise(); return replay(traceFile); } int main(int argc, char **argv) { auto parser = getCommandLineParser(); excmd::option_state options; try { options = parser.parse(argc, argv); } catch (excmd::exception ex) { std::cout << "Error parsing options: " << ex.what() << std::endl; std::exit(-1); } return start(parser, options); }