| 928 | namespace sysmem |
| 929 | { |
| 930 | int Kprintf_HLE() |
| 931 | { |
| 932 | |
| 933 | // Emulate the expected Kprintf functionality: |
| 934 | iopMemWrite32(sp, a0); |
| 935 | iopMemWrite32(sp + 4, a1); |
| 936 | iopMemWrite32(sp + 8, a2); |
| 937 | iopMemWrite32(sp + 12, a3); |
| 938 | pc = ra; |
| 939 | |
| 940 | const std::string fmt = Ra0; |
| 941 | |
| 942 | // From here we're intercepting the Kprintf and piping it to our console, complete with |
| 943 | // printf-style formatting processing. This part can be skipped if the user has the |
| 944 | // console disabled. |
| 945 | |
| 946 | if (!ConsoleLogging.iopConsole.IsActive()) |
| 947 | return 1; |
| 948 | |
| 949 | // maximum allowed size for our buffer before we truncate |
| 950 | constexpr unsigned int max_len = 4096; |
| 951 | char tmp[max_len], tmp2[max_len]; |
| 952 | char* ptmp = tmp; |
| 953 | unsigned int printed_bytes = 0; |
| 954 | unsigned int n = 1, i = 0, j = 0; |
| 955 | |
| 956 | while (fmt[i] && ptmp < std::end(tmp) - 1) |
| 957 | { |
| 958 | const int remaining_buf = static_cast<int>(std::end(tmp) - 1 - ptmp); |
| 959 | switch (fmt[i]) |
| 960 | { |
| 961 | case '%': |
| 962 | j = 0; |
| 963 | tmp2[j++] = '%'; |
| 964 | _start: |
| 965 | // let's check whether this is our null terminator |
| 966 | // before allowing the parser to proceed |
| 967 | if (fmt[i + 1]) |
| 968 | { |
| 969 | switch (fmt[++i]) |
| 970 | { |
| 971 | case '.': |
| 972 | case 'l': |
| 973 | if (j >= max_len) |
| 974 | break; |
| 975 | tmp2[j++] = fmt[i]; |
| 976 | goto _start; |
| 977 | default: |
| 978 | if (fmt[i] >= '0' && fmt[i] <= '9') |
| 979 | { |
| 980 | if (j >= max_len) |
| 981 | break; |
| 982 | tmp2[j++] = fmt[i]; |
| 983 | goto _start; |
| 984 | } |
| 985 | break; |
| 986 | } |
| 987 | } |
nothing calls this directly
no test coverage detected