Adding network to closed-source games
Good Afternoon. I was wondering if it's possible to add networking to PC games that didn't originally have it built in. For instance, let's say that I have Street Fighter II for the PC. Let's assume that there's an API for a network game service(for ex. Kaillera). Ideally, I'd like to connect both players via th Internet and have it play as if there's 2 people connected to their PC. I was thinking about maybe sending just the input commands, but it seems that synchronization and maintaining a persistent state on both machines is next to impossible. Fighting games especially have strict latency requirements. Many games require that input is accurate to within 1/60th of a second. Otherwise, the game would be unplayable. Ideally I'd like to make a program that can: Load any exe and run the game in the window. Intercept some input from the keyboard and pass it off to the game as necessary. Maintain a persistent(and consistent) state of the fight on both machines. It would seem that I'd also need a way to control the frame rate to avoid desync issues. And there also the issue of displaying the same view of the fight on both machines. Btw, this is all windows-based. Am I crazy? Any suggestions?
Largely crazy I think. :(
Even fighting games with built-in networking have latency issues (although DOA on XBox does a pretty good job). The only reverse engineered network games I've seen done that worked were for megadrive emulators - those ran the same app on both machines and transmitted button presses. However just a slight inconsistancy with the input is going to send the two games down different paths (and does, judging from the ones I played).
A more practical way would be a remote-desktop method of making a dumb client which sent input and received an image of the remote app at the current time. That's going to be a lot of image data but over a LAN it might just work well enough. And you've still got latency to contend with.
Even fighting games with built-in networking have latency issues (although DOA on XBox does a pretty good job). The only reverse engineered network games I've seen done that worked were for megadrive emulators - those ran the same app on both machines and transmitted button presses. However just a slight inconsistancy with the input is going to send the two games down different paths (and does, judging from the ones I played).
A more practical way would be a remote-desktop method of making a dumb client which sent input and received an image of the remote app at the current time. That's going to be a lot of image data but over a LAN it might just work well enough. And you've still got latency to contend with.
[size="1"][[size="1"]TriangularPixels.com[size="1"]] [[size="1"]Rescue Squad[size="1"]] [[size="1"]Snowman Village[size="1"]] [[size="1"]Growth Spurt[size="1"]]
Anything *CAN* be done. However, the price often is higher than anyone is likely to want to pay. I believe that this is one of those cases. It'd be cheaper to license the source art and re-implement the game as network-aware.
enum Bool { True, False, FileNotFound };
I'me programming a little app that do exactly what you want to do, its name is Fierce Gear and is an online hack for Guilty Gear XX #reload, Eternal Fighter Zero and Melty Blood ReAct (three fighting game). You can reach the page here: http://fiercegear.combovideos.com
My program work in this way:
1) Load the config file of the game
2) I run the game with "CreateProcess" and put it so sleep
3) I inject my dll into the address space of the game
4) I catch the call to DirectInputCreate and DirectSoundCreate (in this way I have pointer to the device created)
5) Everytime a call to GetDeviceData is performed by the game a personal function of mine is called
6) I catch the input and modify it considering the net code and the inputs from the other machine, writing my input to the keyboard buffer so that the game think it has taken it from the device
7) I catch the call to srand(), rand() (to ensure same randomness over the net)
8) I catch the function that load data from the hdd and send message to the other side saying to wait if the other pc performed a quicker load
Obviously I keep an eye over duplicate inputs and other kind of situations that can bring problems in synchronization.
I use winsock and overlapped I/O, WSArecv called from the completion routine and WSAsend sent if the previous one has finish and if the simulated delay has passed. I pack the input data in a 8 bit unsigned integer and I queue all the inputs between net update. The actual version is 0.2.9.1 experimental, I have to correct some problems but I'm in a point in wich I can truely believe that perfect netplay is possible for a net-delay suffering game like a fast fighting game. Last thing: I use a direct connection from a gamer to another. No server, I have to specify the ip of your enemy (in a 1v1 fashion).
If you want to partecipate send me an email (bjogio@libero.it), I'm searching programmers with good skills in: asm, PE retroengineering and C.
My program work in this way:
1) Load the config file of the game
2) I run the game with "CreateProcess" and put it so sleep
3) I inject my dll into the address space of the game
4) I catch the call to DirectInputCreate and DirectSoundCreate (in this way I have pointer to the device created)
5) Everytime a call to GetDeviceData is performed by the game a personal function of mine is called
6) I catch the input and modify it considering the net code and the inputs from the other machine, writing my input to the keyboard buffer so that the game think it has taken it from the device
7) I catch the call to srand(), rand() (to ensure same randomness over the net)
8) I catch the function that load data from the hdd and send message to the other side saying to wait if the other pc performed a quicker load
Obviously I keep an eye over duplicate inputs and other kind of situations that can bring problems in synchronization.
I use winsock and overlapped I/O, WSArecv called from the completion routine and WSAsend sent if the previous one has finish and if the simulated delay has passed. I pack the input data in a 8 bit unsigned integer and I queue all the inputs between net update. The actual version is 0.2.9.1 experimental, I have to correct some problems but I'm in a point in wich I can truely believe that perfect netplay is possible for a net-delay suffering game like a fast fighting game. Last thing: I use a direct connection from a gamer to another. No server, I have to specify the ip of your enemy (in a 1v1 fashion).
If you want to partecipate send me an email (bjogio@libero.it), I'm searching programmers with good skills in: asm, PE retroengineering and C.
[ILTUOMONDOFUTURO]
bjogio,
how do you synchronize the input on both sides?
I was thinking that a good idea would be to have both
players sycnhronize their time with the same NTP(Network Time
Protocol) server.
Then you wouldn't even have to modify the input at all.
how do you synchronize the input on both sides?
I was thinking that a good idea would be to have both
players sycnhronize their time with the same NTP(Network Time
Protocol) server.
Then you wouldn't even have to modify the input at all.
no, you have to modify it cause if an input is performed at time D you must wait for ack from other side before allow this input to take action, so you must queue the values you are interested to (until the next WSAsend) and erase the buffer at each tick. It's not a matter of time synch (the game work to handle this kind of problems) but of action synch. You cannot achieve perfect synchronization cause the two system will be different in a value proportional to the net delay.
[ILTUOMONDOFUTURO]
Quote:
Original post by Anonymous Poster
Can you explain step 7 to me?
"7) I catch the call to srand(), rand() (to ensure same randomness over the net)"
What do you mean by "to ensure same randomness over the net". Is this for some sort of jitter calculation?
This would use the same seed (srand()) for the random number function (rand()) on both machines, so that both games will generate the same sequence of random numbers.
I catch the call to the srand function and provide a well known seed. The game I'm working on are build with the vs6 C compile (the info found looking at signature with my decompiler) and the implementation of the rand() function that Ms give us generate the same sequence of random numbers given the same seed. So if I know (and set) the "seed" I can say that with N number of call to the rand() function the N° pseudorandom number will be the same on both machine. I do not use the rand() function, the game use it and I must ensure that the same number are generated on both machine cause that values are used on damage calculation and other stuff.
[ILTUOMONDOFUTURO]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement