| 158 | } |
| 159 | |
| 160 | std::vector<N64Recomp::InstructionPatch> get_instruction_patches(const toml::table* patches_data) { |
| 161 | std::vector<N64Recomp::InstructionPatch> ret; |
| 162 | |
| 163 | // Check if the instruction patch array exists. |
| 164 | const toml::node_view insn_patch_data = (*patches_data)["instruction"]; |
| 165 | |
| 166 | if (insn_patch_data.is_array()) { |
| 167 | const toml::array* insn_patch_array = insn_patch_data.as_array(); |
| 168 | ret.reserve(insn_patch_array->size()); |
| 169 | |
| 170 | // Copy all the patches into the output vector. |
| 171 | insn_patch_array->for_each([&ret](auto&& el) { |
| 172 | if constexpr (toml::is_table<decltype(el)>) { |
| 173 | const toml::table& cur_patch = *el.as_table(); |
| 174 | |
| 175 | // Get the vram and make sure it's 4-byte aligned. |
| 176 | std::optional<uint32_t> vram = cur_patch["vram"].value<uint32_t>(); |
| 177 | std::optional<std::string> func_name = cur_patch["func"].value<std::string>(); |
| 178 | std::optional<uint32_t> value = cur_patch["value"].value<uint32_t>(); |
| 179 | |
| 180 | if (!vram.has_value() || !func_name.has_value() || !value.has_value()) { |
| 181 | throw toml::parse_error("Instruction patch is missing required value(s)", el.source()); |
| 182 | } |
| 183 | |
| 184 | if (vram.value() & 0b11) { |
| 185 | // Not properly aligned, so throw an error (and make it look like a normal toml one). |
| 186 | throw toml::parse_error("Instruction patch is not word-aligned", el.source()); |
| 187 | } |
| 188 | |
| 189 | ret.push_back(N64Recomp::InstructionPatch{ |
| 190 | .func_name = func_name.value(), |
| 191 | .vram = (int32_t)vram.value(), |
| 192 | .value = value.value(), |
| 193 | }); |
| 194 | } |
| 195 | else { |
| 196 | throw toml::parse_error("Invalid instruction patch entry", el.source()); |
| 197 | } |
| 198 | }); |
| 199 | } |
| 200 | |
| 201 | return ret; |
| 202 | } |
| 203 | |
| 204 | std::vector<N64Recomp::FunctionTextHook> get_function_hooks(const toml::table* patches_data) { |
| 205 | std::vector<N64Recomp::FunctionTextHook> ret; |