I've been looking at Warcraft III today, and had the problem of single player campaigns not showing up. The reason behind this is explained at http://bugs.winehq.org/show_bug.cgi?id=2075, and sure enough adding the special case described for the I64 argument type specification solves the problem in W3. Now I'm wondering how the problem should really be solved. Currently most (possibly all) of the *printf functions in msvcrt call MSVCRT_vsnprintfW. Should the same be done for vsnprintf, or should there be an independent MSVCRT_vsnprintfA? Either way I don't really know how the implementation would work. I was kind of hoping that this might be an okay place to start learning about WINE development, so if this in fact hinges on something far more complicated than I've been able to grasp, somebody please point this out to me :). Any pointers? Thanks, Aneurin Price
Aneurin Price wrote:
I've been looking at Warcraft III today, and had the problem of single player campaigns not showing up. The reason behind this is explained at http://bugs.winehq.org/show_bug.cgi?id=2075, and sure enough adding the special case described for the I64 argument type specification solves the problem in W3. Now I'm wondering how the problem should really be solved. Currently most (possibly all) of the *printf functions in msvcrt call MSVCRT_vsnprintfW. Should the same be done for vsnprintf, or should there be an independent MSVCRT_vsnprintfA? Either way I don't really know how the implementation would work.
What I'd recommend is submitting a patch which converts the MSVCRT format string specifiers into glibc style specifiers, and see what Alexandre says. It should be a small patch.
If he isn't happy, find a printf implementation somewhere of a suitable license, munge it to act in the right way (with test cases ideally) and submit. That was the way Alexandre seemed to prefer last time this came up.
I was kind of hoping that this might be an okay place to start learning about WINE development, so if this in fact hinges on something far more complicated than I've been able to grasp, somebody please point this out to me :).
Nope, it's not all that complicated. Go for it! Don't be afraid to ask for help if you get stuck.
thanks -mike
Mike Hearn wrote:
Aneurin Price wrote:
I've been looking at Warcraft III today, and had the problem of single player campaigns not showing up. The reason behind this is explained at http://bugs.winehq.org/show_bug.cgi?id=2075, and sure enough adding the special case described for the I64 argument type specification solves the problem in W3. Now I'm wondering how the problem should really be solved. Currently most (possibly all) of the *printf functions in msvcrt call MSVCRT_vsnprintfW. Should the same be done for vsnprintf, or should there be an independent MSVCRT_vsnprintfA? Either way I don't really know how the implementation would work.
What I'd recommend is submitting a patch which converts the MSVCRT format string specifiers into glibc style specifiers, and see what Alexandre says. It should be a small patch.
Well, for that particular function something like the attached modification should do[0], but obviously it's a bit silly to convert like that for every function. Currently all the wide printf functions in mscvrt ultimately call vsnprintfW (which itself uses native sprintf), though sometimes through multiple levels of indirection - eg. fwprintf -> vwprintf -> vfwprintf -> _vsnwprintf -> vsnprintfW or _snwprintf -> ntdll._snwprintf -> vsnprintfW. Are there reasons for this, or is it just cruft? It looks to me like it would be a good idea to start by making them all call vsnprintfW and have that convert the I, I32 and I64 arguments, before calling sprintf[1].
The non-unicode printf functions seem to call each other arbitrarily (?), but the native functions used are vsnprintf, snprintf, vsprintf, and sprintf. It might be worth then making all the functions directly analogous to their wide counterparts for simplicity.
Finally, I'd like some clarification on what the %S and %C type specifiers[2] are used for. My understanding is that the string/character should just be converted to/from unicode as appropriate, not caring about data loss in the latter case, since that would only happen when you're using non-unicode functions anyway.
If he isn't happy, find a printf implementation somewhere of a suitable license, munge it to act in the right way (with test cases ideally) and submit. That was the way Alexandre seemed to prefer last time this came up.
Maybe I should start looking into how to use register_printf_function [3].
Phew, I hope that made sense :). Thanks for your help, Aneurin Price
[0] Though only on 32-bit platforms, since long and long long needn't always be 32/64 bit? How would one ensure a particular size regardless of platform?
[1] I don't actually see why vsnprintfW has been made the main printf function rather than (say) sprintfW, since natively swprintf is used anyway. This is all assuming that sprintf can be made to act like the other *printf functions with appropriate arguments, since I haven't looked into that yet. I'm making this assumption for the moment as that's what's currently being done:).
[2] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HT...
[3] http://www.gnu.org/software/libc/manual/html_node/Registering-New-Conversion...