I'm ready to begin work on a basic_ifstream implementation for Wine, which is needed for the game Vampire Secrets among others.
http://bugs.winehq.org/show_bug.cgi?id=28612
First I'd like to check that Piotr isn't already working on this. If not, I'm open to any advice on how to proceed. My plan is to create fstream.c, and use string.c as a guide.
Josh
On Oct 26, 2011, at 11:59 AM, Josh Juran wrote:
I'm ready to begin work on a basic_ifstream implementation for Wine, which is needed for the game Vampire Secrets among others.
http://bugs.winehq.org/show_bug.cgi?id=28612
First I'd like to check that Piotr isn't already working on this. If not, I'm open to any advice on how to proceed. My plan is to create fstream.c, and use string.c as a guide.
Well, it turns out that the game creates an ifstream for its intro movie and then uses a completely different mechanism to read from it. Defining a (nearly) empty constructor and destructor for basic_ifstream<char> was sufficient to make things work.
The good news is that this ticket can be resolved if the patch attached to it and included below (or one like it) is applied. The bad news is that I won't be providing an actual implementation or otherwise working on this any further.
Josh
diff --git a/dlls/msvcp90/ios.c b/dlls/msvcp90/ios.c index 84dfb17..4290469 100644 --- a/dlls/msvcp90/ios.c +++ b/dlls/msvcp90/ios.c @@ -1727,3 +1727,35 @@ basic_ostream_char* __thiscall basic_ostream_char_write(basic_ostream_char *this FIXME("(%p %s %lu) stub\n", this, debugstr_a(str), count); return NULL; } + +static const vtable_ptr basic_ifstream_char_vtable; + +typedef struct _basic_ifstream_char +{ + const vtable_ptr *vtable; + + int filler[ 140 / sizeof (int) - sizeof (const vtable_ptr*) ]; +} +basic_ifstream_char; + +/* ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBDHH@Z */ +/* ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEBDHH@Z */ +DEFINE_THISCALL_WRAPPER(basic_ifstream_char_ctor, 16) +basic_ifstream_char* __thiscall basic_ifstream_char_ctor(basic_ifstream_char *this, const char *path, int mode, int prot) +{ + FIXME("(%p, %s, %d, %d) stub\n", this, path, mode, prot); + + this->vtable = &basic_ifstream_char_vtable; + + return this; +} + +/* ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAEXXZ */ +/* ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAAXXZ */ +DEFINE_THISCALL_WRAPPER(basic_ifstream_char_vbase_dtor, 4) +basic_ifstream_char* __thiscall basic_ifstream_char_vbase_dtor(basic_ifstream_char *this) +{ + FIXME("(%p) stub\n", this); + + return this; +} diff --git a/dlls/msvcp90/msvcp90.spec b/dlls/msvcp90/msvcp90.spec index 33d5619..f43a669 100644 --- a/dlls/msvcp90/msvcp90.spec +++ b/dlls/msvcp90/msvcp90.spec @@ -590,7 +590,7 @@ @ stub -arch=win64 ??0?$basic_fstream@_WU?$char_traits@_W@std@@@std@@QEAA@XZ @ stub -arch=win32 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PAU_iobuf@@@Z @ stub -arch=win64 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEAU_iobuf@@@Z -@ stub -arch=win32 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBDHH@Z +@ thiscall -arch=win32 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBDHH@Z(ptr long long) basic_ifstream_char_ctor @ stub -arch=win64 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEBDHH@Z @ stub -arch=win32 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBGHH@Z @ stub -arch=win64 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEBGHH@Z @@ -1907,7 +1907,7 @@ @ stub -arch=win64 ??_D?$basic_fstream@GU?$char_traits@G@std@@@std@@QEAAXXZ @ stub -arch=win32 ??_D?$basic_fstream@_WU?$char_traits@_W@std@@@std@@QAEXXZ @ stub -arch=win64 ??_D?$basic_fstream@_WU?$char_traits@_W@std@@@std@@QEAAXXZ -@ stub -arch=win32 ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAEXXZ +@ thiscall -arch=win32 ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAEXXZ(ptr) basic_ifstream_char_vbase_dtor @ stub -arch=win64 ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAAXXZ @ stub -arch=win32 ??_D?$basic_ifstream@GU?$char_traits@G@std@@@std@@QAEXXZ @ stub -arch=win64 ??_D?$basic_ifstream@GU?$char_traits@G@std@@@std@@QEAAXXZ
On Thu, Oct 27, 2011 at 2:01 AM, Josh Juran josh@iswifter.net wrote:
@ stub -arch=win64 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAA@PEBDHH@Z @ stub -arch=win64 ??_D?$basic_ifstream@DU?$char_traits@D@std@@@std@@QEAAXXZ
You forgot to update the win64 stubs in the spec file.
Octavian
On 10/27/11 2:01 AM, Josh Juran wrote:
On Oct 26, 2011, at 11:59 AM, Josh Juran wrote:
I'm ready to begin work on a basic_ifstream implementation for Wine, which is needed for the game Vampire Secrets among others.
In order to implement it correctly lots of functions/classes needs to be implemented first. I've started stubbing some of them but there's still lots to be done.
Well, it turns out that the game creates an ifstream for its intro movie and then uses a completely different mechanism to read from it. Defining a (nearly) empty constructor and destructor for basic_ifstream<char> was sufficient to make things work.
It may happen because of inlining some functions. The game may also use created streams later.
+static const vtable_ptr basic_ifstream_char_vtable;
+typedef struct _basic_ifstream_char +{
- const vtable_ptr *vtable;
- int filler[ 140 / sizeof (int) - sizeof (const vtable_ptr*) ];
+} +basic_ifstream_char;
It's not good to add an incomplete structure. We'll end having lots of bugs that will need to be debugged to find where the problem is. Especially adding uninitialized vtable pointer is not a good idea.
I think it should be implemented by adding all fstream class dependencies first. Thanks to it it will be possible to create a complete basic_ifstream_char structure.
+basic_ifstream_char* __thiscall basic_ifstream_char_ctor(basic_ifstream_char *this, const char *path, int mode, int prot) +@ thiscall -arch=win32 ??0?$basic_ifstream@DU?$char_traits@D@std@@@std@@QAE@PBDHH@Z(ptr long long) basic_ifstream_char_ctor
Arguments in spec file are different then in ios.c.
Cheers, Piotr
On Oct 27, 2011, at 12:35 AM, Piotr Caban wrote:
On 10/27/11 2:01 AM, Josh Juran wrote:
On Oct 26, 2011, at 11:59 AM, Josh Juran wrote:
I'm ready to begin work on a basic_ifstream implementation for Wine, which is needed for the game Vampire Secrets among others.
In order to implement it correctly lots of functions/classes needs to be implemented first. I've started stubbing some of them but there's still lots to be done.
Well, it turns out that the game creates an ifstream for its intro movie and then uses a completely different mechanism to read from it. Defining a (nearly) empty constructor and destructor for basic_ifstream<char> was sufficient to make things work.
It may happen because of inlining some functions.
I don't understand this explanation.
Most games don't have this issue. It looks like the developer was originally using ifstream to read the file and then switched to something else, but forgot to remove the ifstream object definition.
The game may also use created streams later.
Possible in theory, but unlikely.
It's not good to add an incomplete structure. We'll end having lots of bugs that will need to be debugged to find where the problem is. Especially adding uninitialized vtable pointer is not a good idea.
I agree that this patch should not go into Wine as is.
I think it should be implemented by adding all fstream class dependencies first. Thanks to it it will be possible to create a complete basic_ifstream_char structure.
I appreciate your (and others') willingness to provide feedback. Unfortunately, my job in this case is to make certain apps work (by hack or by crack) and move on.
Josh
On Fri, Oct 28, 2011 at 01:30, Josh Juran josh@iswifter.net wrote:
I appreciate your (and others') willingness to provide feedback. Unfortunately, my job in this case is to make certain apps work (by hack or by crack) and move on.
What you could do is add/update the AppDB entry for this program, and link to your bug (hence patch).
Frédéric