🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Untitled

posted in DruinkJournal
Published April 08, 2009
Advertisement
My Tiberian Sun network patch I was working on yesterday is done and working, hooray!

I did manage to get the code finished on the bus on the way home, but I had a little more trouble than I expected with getting it to run on Windows 98, due to two problems.
Firstly, it seems that the method of export forwarding I mentioned yesterday doesn't work on Windows 98. Windows reported that "Ordinal 133 does not exist in wsock32.dll". That was referring to WSACleanup(), a function that was forwarded to ws2_32.dll. I checked that the ordinal and name matched in the proxy DLL, the real wsock32.dll and ws2_32.dll and they all did. It worked fine on Vista, just not on '98.
So, I had to change my proxy DLL to implement all of the functions that game.exe tries to use (Thankfully I didn't need to implement all of the ones in wsock32.dll or I'd be at it all night), and just forward them to the versions in the real wsock32.dll.

The second problem was that starting with Visual Studio 2008, you can't write apps that will run on Windows 95, 98 or ME. The earliest you can target is Windows 2000. Setting WINVER and _WIN32_WINNT to 0x400 (Windows 95 version number) just causes the linker to spit out a version 5.0 file (Which is XP I think, it might be 2000 now I think about it though). That wasn't too bad I guess, since I have Visual Studio 2005 on my server, so I could compile it with that.

The proxy DLL does some logging too; it spews some information about the functions being called to the debug output (Via OutputDebugString()), and to a file in D:/winsock.log. I was going to make it read a registry key to enable / disable logging and to specify where to log to, but I never got around to it. I'll maybe do that on the bus on the way home today / tonight, since playing a network game for a couple of minutes produced a 134KB log file...

So, if anyone wants it, you can download the DLL file Here (Zipped) - just chuck it in your Tiberian Sun directory and it'll convert all IPX traffic to UDP instead. You'll need to make sure that everyone playing has the DLL in their game directory, and I've tested it on Windows 98 SE and Windows Vista Home Premium. Please let me know if you get it working on other OS's.
The source code is also available Here for anyone who wants it. The VS2008 solution and project are a bit out of date - I only ever built the debug config, and I didn't add the resource file (Version info) to the project. The VS2005 solution and project should work fine though.

And, for anyone who cares what the log file looks like:
Log starting------------WSAStartup(0x0101, 0x02ABE200)Patched from "C:\Windows\system32\wsock32.dll" okWSAStartup(0x0101, 0x068E8EE0)hooked socket(6, 2, 1000), returns 712hooked socket(6, 2, 1000), returns 648normal bind(648)IPX bind(648, len=14) to 00-00-00-00, 00-00-00-00-00-00, port 0 => 0hooked getsockopt(648, 1000, 16397, 0x0012f2cc, 4)hooked getsockopt(648, 1000, 16391, 0x0012f2e8, 24)normal bind(712)IPX bind(712, len=16) to 00-00-00-00, 00-00-00-00-00-00, port 5000 => 0normal setsockopt(712, 65535, 32, [0x00000001], 4) => 0hooked setsockopt(712, 1000, 16384, [0x00000004], 4)hooked setsockopt(712, 1000, 16385, [0x00000004], 4)normal setsockopt(712, 65535, 4098, [0x00020000], 4) => 0normal setsockopt(712, 65535, 4097, [0x00020000], 4) => 0Hooked sendto(712, 255.255.255.255:5000) => 468Hooked recvfrom(712, 192.168.1.3:5000) => 468Hooked sendto(712, 255.255.255.255:5000) => 468Hooked recvfrom(712, 192.168.1.3:5000) => 468Hooked recvfrom(712, 192.168.1.9:5000) => 468Hooked sendto(712, 255.255.255.255:5000) => 468Hooked recvfrom(712, 192.168.1.3:5000) => 468Hooked recvfrom(712, 192.168.1.9:5000) => 468
The "=> 0" or "=> 468" lines are the return value of the real function.
The game seems to create two sockets, but only use one of them (Socket ID 712), I'm not really sure what the bind to an all-zero address is supposed to do.
The first two getsockopt() calls are the game getting the number of adapters (The hooked version returns 1), and then getting the IPX address and status of that adapter (The hooked version returns an all-zeros address). The game then binds to that adapter on port 5000, enables broascast (setsockopt(712, 65535, 32, ...), sets a couple of random IPX settings (16384=IPX_PTYPE (packet type), 16385=IPX_FILTERPTYPE, (recv only packets of this type), hooked version ignores changes). Then the game sets the send and recv buffers to 128KB each, then starts sending data. All fairly simple (Thankfully).

Anyway, back to work for me...
Previous Entry Untitled
0 likes 1 comments

Comments

andwan0
Is this patch generic (as in it should work for all IPX win sock games...) or just Tiberian Sun game specific?

If it's specific, how can we adapt this code for other games, eg. Theme Hospital,
August 14, 2009 04:04 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement