Those of you with experience programming floating point code are probably facepalming already. The short answer is that it's directly equating floating point values which is incredibly stupid.

While this exact code is called on every context creation, it clearly doesn't cause anything problematic for most non-Tasofro apps. This is because of the FPU rounding mode. In the default setting, it will always converge because the two values are constants. However, Tasofro sets the FPU Control Word to 0A7F at some point, which means it always rounds up rather than rounds to nearest. This means that the value will never converge. So it just gets stuck in an infinite loop.

The fix:

FPUCW 0A7F -> FPUCW 027F during first call to IDirect3DDevice::SetFVF(), resetting the rounding mode to default, when the relevant context is created. Or the entire code block that is called at th123_102.41DAD7 can also be wrappered by this.

The fix in the DLL is incomplete at this time, it'll still freeze sometimes. Need to put a wrapper on a lot more d3d calls/threads than I have at this time. (I would just find and kill the 0A7F completely, except netplay synchronization is an issue.)

Crashes in certain menus and when Sanae is picked

Symptoms:

When entering various menus in the game or entering any fight where Sanae is involved, the game will immediately crash.

The bug:

th123's GetGlyphOutline() code does not check to see if it returned an invalid glyph, since this never happens on Windows. So, whenever any text includes a glyph that is returned as invalid by wine, such as a space, the game will just crash with an integer divide by zero.

The fix:

Override GetGlyphOutline() and return a faked response for spaces.

The game runs too slowly

Symptoms:

Instead of running at about 60-62fps, like the game is supposed to, it'll run closer to 53fps. This is not ideal.

The bug:

This seems to be a wine issue. The game calls timeBeginPeriod with a timer period of 16ms and then simply waits for the events to roll in, which is fairly standard. But unfortunately it's getting something closer to a 19ms period, which is frankly just strange.

The fix:

I hacked around this by setting the timer period to 14ms. This oddly makes it run at right around 16ms exactly, leading to a steady 62-63fps. Which is close enough for use, really. For a constant 60fps turn on vsync in your video drivers.

Missing textures with AIGLX:

Symptoms:

With AIGLX in use many textures are just outright missing. They are not rendered incorrectly, they're simply just not there. However, not all are invisible, which is honestly a bit confusing.

Anything that is rendered with depth buffer use, such as shadows, Reimu 2B/2C, Sanae 6C, etc show a only one pixel wide chunk of the texture.

The bug:

Unknown. Forcing a call to SetViewport() at the right place seems to fix it for most of the cast, but then Utsuho comes along and it completely ceases to work again. Is this related to the depth buffer itself, the depth function, or what?

This is also most likely the bug that is causing PatchCon to be invisible when I get it to run with the freeze workaround.

Freezes when canceling netplay host or connection

Symptoms:

When you host a server or try to connect to a server, and then cancel with the escape key, the game freezes and gets stuck in an infinite loop. Music continues to play. Actual netplay still works fine.

The bug:

Unknown. Probably that a winsock call is getting hung up somewhere. Either way it doesn't want me to debug it.

The game crashes when I close the window

Symptoms:

If you close the window while the game is running it'll probably crash and leave a zombie process behind that will prevent you from clicking on the stupid message box Wine brings up. You'll likely need to run 'pkill th123' or something to get it working again. This does not occur when you exit normally.

The bug:

Seems to be a threading issue: Wine tries to create another child context after the current ones have been deleted, since apparently the th123 render thread is still going, fails, and summarily explodes.

I don't have a fix for this at this time, just exit the game normally or kill the game's process.