PatchFunc Functions.
| 885 | |
| 886 | // PatchFunc Functions. |
| 887 | void Patch::PatchFunc::patch(PatchGroup* group, const std::string_view cmd, const std::string_view param) |
| 888 | { |
| 889 | #define PATCH_ERROR(fstring, ...) \ |
| 890 | Console.Error(fmt::format("(Patch) Error Parsing: {}={}: " fstring, cmd, param, __VA_ARGS__)) |
| 891 | |
| 892 | // [0]=PlaceToPatch,[1]=CpuType,[2]=MemAddr,[3]=OperandSize,[4]=WriteValue |
| 893 | const std::vector<std::string_view> pieces(StringUtil::SplitString(param, ',', false)); |
| 894 | if (pieces.size() != 5) |
| 895 | { |
| 896 | PATCH_ERROR("Expected 5 data parameters; only found {}", pieces.size()); |
| 897 | return; |
| 898 | } |
| 899 | |
| 900 | std::string_view addr_end, data_end; |
| 901 | const std::optional<patch_place_type> placetopatch = LookupEnumName<patch_place_type>(pieces[0], s_place_to_string); |
| 902 | const std::optional<patch_cpu_type> cpu = LookupEnumName<patch_cpu_type>(pieces[1], s_cpu_to_string); |
| 903 | const std::optional<u32> addr = StringUtil::FromChars<u32>(pieces[2], 16, &addr_end); |
| 904 | const std::optional<patch_data_type> type = LookupEnumName<patch_data_type>(pieces[3], s_type_to_string); |
| 905 | std::optional<u64> data = StringUtil::FromChars<u64>(pieces[4], 16, &data_end); |
| 906 | u8* data_ptr = nullptr; |
| 907 | |
| 908 | if (!placetopatch.has_value()) |
| 909 | { |
| 910 | PATCH_ERROR("Invalid 'place' value '{}' (0: on boot only, 1: continuously, 2: on boot and continuously, 3: on boot and when enabled in the GUI)", pieces[0]); |
| 911 | return; |
| 912 | } |
| 913 | if (!addr.has_value() || !addr_end.empty()) |
| 914 | { |
| 915 | PATCH_ERROR("Malformed address '{}', a hex number without prefix (e.g. 0123ABCD) is expected", pieces[2]); |
| 916 | return; |
| 917 | } |
| 918 | if (!cpu.has_value()) |
| 919 | { |
| 920 | PATCH_ERROR("Unrecognized CPU Target: '{}'", pieces[1]); |
| 921 | return; |
| 922 | } |
| 923 | if (!type.has_value()) |
| 924 | { |
| 925 | PATCH_ERROR("Unrecognized Operand Size: '{}'", pieces[3]); |
| 926 | return; |
| 927 | } |
| 928 | if (type.value() != BYTES_T) |
| 929 | { |
| 930 | if (!data.has_value() || !data_end.empty()) |
| 931 | { |
| 932 | PATCH_ERROR("Malformed data '{}', a hex number without prefix (e.g. 0123ABCD) is expected", pieces[4]); |
| 933 | return; |
| 934 | } |
| 935 | } |
| 936 | else |
| 937 | { |
| 938 | // bit crappy to copy it, but eh, saves writing a new routine |
| 939 | std::optional<std::vector<u8>> bytes = StringUtil::DecodeHex(pieces[4]); |
| 940 | if (!bytes.has_value() || bytes->empty()) |
| 941 | { |
| 942 | PATCH_ERROR("Malformed data '{}', a hex string without prefix (e.g. 0123ABCD) is expected", pieces[4]); |
| 943 | return; |
| 944 | } |