Skip to content

Debugger: sceKernelPrintf improvement, QOL adjustments#17263

Merged
hrydgard merged 1 commit intohrydgard:masterfrom
Nemoumbra:kernel-printf
Apr 11, 2023
Merged

Debugger: sceKernelPrintf improvement, QOL adjustments#17263
hrydgard merged 1 commit intohrydgard:masterfrom
Nemoumbra:kernel-printf

Conversation

@Nemoumbra
Copy link
Collaborator

  1. Now sceKernelPrintf can print %f floats. Note: it doesn't use the floating registers (if anyone has some evidence of a real PSP game that prepares f0 or something before the call, please do show).
    Example with a1 equal to 0x3f8ccccd:
    image

  2. The "Copy Float (32 bit)" menu item has been moved to its own section because I suspect some people might have memorized the layout and thus experience slight inconveniences due to it now being the last element. Well, that's no longer a problem. We may also later add other floating types here.

image

  1. This commit does not fix the recently added menu item so I decided to do that.
    I have also renamed it to have consistent terms across the code:
    image

  2. Lastly, check the notes here: https://en.cppreference.com/w/cpp/io/basic_stringstream/str

@hrydgard
Copy link
Owner

Yeah seems likely that printf (varargs) parameters go through regular registers. I do seem to recall that floating point arguments to regular functions can go through fp registers, but didn't check now.

@hrydgard hrydgard added this to the v1.15.0 milestone Apr 11, 2023
Comment on lines +1183 to +1187
stream << f_arg;
result += stream.str();

++i;
stream.str(std::string()); // Reset the stream
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify my previous comment about this, here's what I would have done here:

char temp[64];
snprintf(temp, sizeof(temp), "%f", f_arg);
result += temp;

Though, to be fair, yours is better "C++", mine is just reflective of my somewhat excessive obsession with avoiding allocations. Doing that is important when running PPSSPP in debug mode for things that happen a lot, but since this shouldn't be very spammy, doing it the C++ way is fine and I'm not even sure in reality that there's more than one excessive allocation happening here (the stringstream has to allocate a buffer, while my way allocates it on the stack which is cheaper).

@fp64
Copy link
Contributor

fp64 commented Apr 12, 2023

The raw "%f" (which both operator<< and std::to_string use under the hood) in general gives you "wrong" float representation (produces different bitpattern when fed to e.g. strtof). The simplest version that guarantees (assuming round-to-nearest rounding mode) float->string->float round-trip is "%.9g". Not sure what the desired behaviour for sceKernelPrintf is, but for right-click menu I would expect "value-preserving" representation.

As for stringstream... why not use aforementioned std::to_string?

@hrydgard
Copy link
Owner

That's a good point about copy - roundtrippable would be good there.

@Nemoumbra
Copy link
Collaborator Author

#17203 (comment)
Here I explained my choice with using the stringstream and not std::to_string()

@fp64
Copy link
Contributor

fp64 commented Apr 12, 2023

Here I explained my choice with using the stringstream and not std::to_string()

Oh, yes, I was wrong: operator<< uses (by default) "%g" (see https://en.cppreference.com/w/cpp/locale/num_put/put for details) and std::to_string uses "%f".

Still, "%g" is "%.6g", which is not enough for round-trip.

@Nemoumbra
Copy link
Collaborator Author

Of course, we're not done with sceKernelPrintf. I only added the %f flag, but no precision params are available as of now. I guess, this is a PoC.
This is what I think we can do next:

  1. Add support for things like "%.2f". I think this will downgrade the current precision we have for %f, but that's how the PSP works and... we want PPSSPP to emulate it, don't we?
  2. If sceKernelPrintf supports this %g, it should also be added.
  3. Finally, if the precision can be improved without breaking the correctness, improve the "Copy Float (32 bit)" option.

@fp64
Copy link
Contributor

fp64 commented Apr 13, 2023

float->string->float round-trip is "%.9g"

For those curious: the formula is $1 + \lceil p \times \log_{10} 2 \rceil$ (and $\lfloor (p - 1) \times \log_{10} 2 \rfloor$ for longest safe string->float->string round-trip, which is 6 for float, which has $p = 24$). See e.g. this.

@Nemoumbra Nemoumbra deleted the kernel-printf branch August 23, 2023 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants