| 674 | } |
| 675 | |
| 676 | bool read_config(const std::filesystem::path& config_path, RSPRecompilerConfig& out) { |
| 677 | RSPRecompilerConfig ret{}; |
| 678 | |
| 679 | try { |
| 680 | const toml::table config_data = toml::parse_file(config_path.u8string()); |
| 681 | std::filesystem::path basedir = std::filesystem::path{ config_path }.parent_path(); |
| 682 | |
| 683 | std::optional<uint32_t> text_offset = config_data["text_offset"].value<uint32_t>(); |
| 684 | if (text_offset.has_value()) { |
| 685 | ret.text_offset = text_offset.value(); |
| 686 | } |
| 687 | else { |
| 688 | throw toml::parse_error("Missing text_offset in config file", config_data.source()); |
| 689 | } |
| 690 | |
| 691 | std::optional<uint32_t> text_size = config_data["text_size"].value<uint32_t>(); |
| 692 | if (text_size.has_value()) { |
| 693 | ret.text_size = text_size.value(); |
| 694 | } |
| 695 | else { |
| 696 | throw toml::parse_error("Missing text_size in config file", config_data.source()); |
| 697 | } |
| 698 | |
| 699 | std::optional<uint32_t> text_address = config_data["text_address"].value<uint32_t>(); |
| 700 | if (text_address.has_value()) { |
| 701 | ret.text_address = text_address.value(); |
| 702 | } |
| 703 | else { |
| 704 | throw toml::parse_error("Missing text_address in config file", config_data.source()); |
| 705 | } |
| 706 | |
| 707 | std::optional<std::string> rom_file_path = config_data["rom_file_path"].value<std::string>(); |
| 708 | if (rom_file_path.has_value()) { |
| 709 | ret.rom_file_path = concat_if_not_empty(basedir, rom_file_path.value()); |
| 710 | } |
| 711 | else { |
| 712 | throw toml::parse_error("Missing rom_file_path in config file", config_data.source()); |
| 713 | } |
| 714 | |
| 715 | std::optional<std::string> output_file_path = config_data["output_file_path"].value<std::string>(); |
| 716 | if (output_file_path.has_value()) { |
| 717 | ret.output_file_path = concat_if_not_empty(basedir, output_file_path.value()); |
| 718 | } |
| 719 | else { |
| 720 | throw toml::parse_error("Missing output_file_path in config file", config_data.source()); |
| 721 | } |
| 722 | |
| 723 | std::optional<std::string> output_function_name = config_data["output_function_name"].value<std::string>(); |
| 724 | if (output_function_name.has_value()) { |
| 725 | ret.output_function_name = output_function_name.value(); |
| 726 | } |
| 727 | else { |
| 728 | throw toml::parse_error("Missing output_function_name in config file", config_data.source()); |
| 729 | } |
| 730 | |
| 731 | // Extra indirect branch targets (optional) |
| 732 | const toml::node_view branch_targets_data = config_data["extra_indirect_branch_targets"]; |
| 733 | if (branch_targets_data.is_array()) { |
no test coverage detected