Tuesday, December 21, 2010

More on Innocent Tears & [Native] XInput support.

Okay, I made a quick examination of the game's contents to see how tough it will be to get this game working. So far, I hate to say it, but it's going to be rather tedious :( This game contains multiple .xbe files besides the default.xbe itself that are loaded at different times while the game is running. One for intros, gameplay, movie play back, etc. It can be done, but it's going to be really annoying! Fortunately, I learned how to handle this situation with Unreal Championship. We'll have to launch the specified .xbe file each time in order to progress through the game. Cxbx saves the launch data as CxbxLaunchData.bin and loads it when necessary so the game can function properly. Then there are some new DirectSound APIs I have to add (one looks really daunting) and maybe we'll get somewhere. Either way, the compat list is now 40! Thanks to everyone who helped make Cxbx what it is today, including the fans and other enthusiasts that refused to let it die!

"Wait, you added XInput support?" Yup, XInput for the 360 controller is supported now, but for some reason, it works on some games, but doesn't work on others :( I don't know why this is, but I'll continue to look into it. Using DirectInput for the 360 controller isn't really desirable since we miss out on rumble and the d-pad, so I added it. Btw, is this desirable for you guys? If so, then as a result, Cxbx won't support Win2k anymore because XInput only works on XP and later. Just so you know.

Just thought I'd throw this quick update out there for you (while I actually have the chance).


Random update(s) & OpenGL project updates.

Yup, that's right. I'm still kicking! And now that I have a spare moment, I thought I'd share some good news with you all. Nothing spectacular, but hopefully this might interest someone out there :)

As you can see here, the game known as Innocent Tears is showing stuff. This screenshot was not taken by me, btw. It was taken by Bill_gates (no, not THE bill gates, the one on ngemu!) and I don't have this game for myself (yet) but since it uses XDK 4627, I think getting it working passed this screen won't be too hard.

The next thing I wanted to mention was that I finally figured out what was causing Azurik to hang in XP. Turns out it was an Xbox exclusive flag being set that matched a PC flag. The flags MEM_NOZERO (Xbox) and MEM_ROTATE (PC) have the exact same values and causes failures when used with MEM_COMMIT. So all I had to do was omit that flag, and bam, it works again. Why this flag combination works on Vista and later is beyond me, but meh, I'm glad I solved the problem on XP. Azurik still looks rather horriffic going ingame (I've never seen such major distortions in any game to date), and Cxbx generates some funky pushbuffer results for it. No clue how I'm going to emulate this game properly :(

One more thing, I started writing my Xbox Direct3D -> OpenGL 1.5 driver last week in my spare time. So far, it works okay, but it still has a long way to go until it is ready to handle Cxbx. It wasn't really hard or anything, just having to fix annoying bugs to get it to work and trying to support the large array of features and formats is going to take time. It's not intended to replace the actual Direct3D .dlls, but it's (right now) a customized .dll that I aptly named d3d8_xbox.dll that is called instead of d3d8.dll, but you still have to link it with the project. Right now, I'm just testing it against DXSDK examples to make sure it works okay. Here's what I did so far:
  • D3DDevice creation and OpenGL initialization for windowed and fullscreen modes. Also uses glew to initialize the required extensions, saving me precious time and headache.
  • Primitive rendering via D3DDevice::DrawVertices[UP] and D3DDevice::Begin/End. Right now, it uses immediate mode because my vertex array code kept crashing, but for now, getting it to work is the primary concern. Any calls to D3DDevice::DrawPrimitive[UP] are redirected to the above by default. Indexed geometry is not yet supported. Also, every primitive type is supported, so no more primitive patching for non standard primitive types like D3DPT_LINELOOP, D3DPT_QUADLIST and D3DPT_QUADSTRIP! This should run much faster in Robotech: Battlecry and Panzer since they rely on Quad rendering heavily. Also, I'm going to stick with immediate mode for D3DDevice::Begin/End since that's basically what it is, and speed isn't critical for these related APIs.
  • Very basic push buffer emulation via D3DDevice::BeginPush/EndPush. Once again, I'm using immediate mode for it. Works like a charm.
  • World, View and Projection matrices/transformations. I found another D3D -> OpenGL wrapper out there and got the idea for how to do it from that project (dxwgl, IIRC). Before then, I couldn't figure out how to do it. The solution was simple once I understood how it worked.
  • Lighting. It works, but only when I don't set the light position :/ I wonder why that is... Btw, is there an OpenGL equivelant to the "Range" field in D3DLIGHT?
  • Textures and surfaces work, but I only wrote support for D3DFMT_X8R8G8B8 and D3DFMT_A8R8G8B8 so far. Textures use the standard 2D texture, but surfaces use texture rectangles since they are more efficient for such an operation. Special care has to be taken into consideration when dealing with surfaces to make sure they behave properly when rendering normal 3D geometry with certain render states. For instance, I have to disable almost every render/texture state prior to rendering it, but it pays off with speed. My surface code is about 4x faster than Direct3D itself, even when using immediate mode!
  • Various render states. I haven't finished adding all the renderstates, but many of the renderstates not supported by standard Direct3D have been implemented, so we no longer have to worry about those!
There are many more features to go, but give me a month, and hopefully it should be working at a satisfactory level. The big thing that troubles me is converting the vertex/pixel shaders to OpenGL vertex/fragment programs. I can use NVparse and do this easily, but then we'll be limited to NVIDIA cards and ATI users will be left out, or is there an equivelant library for ATI users? If not, I'll try to use the ARB versions for both. Okay? If it works, then we can kiss many of our compatibility problems goodbye!

So, there you have it. This is everything I've been up to so far. I'm still having it rough IRL (well, not too bad since I have stable housing now) but at least I have a bit more free time atm (but I can't spend it all on Cxbx unfortunately). Isn't open source a great way to go?


EDIT: I found this today: http://realmforge.tigris.org/source/browse/realmforge/trunk/src/Axiom/RenderSystems/OpenGL/ATI/PixelShader.cs?revision=5&view=markup

It's in C#, but maybe a bit of hope for the ATI users for a working vs/ps1.1 -> ATI vertex/fragment program conversion.