Legacy GM GGPO netcode DLL; overwriting GM:S by memory address

Drell

Member
Hello all!

UPDATE: I've decided to post here about my solution, but feel free to PM me about questions.

I've essentially mirrored the GGPO framework in my game using my own code combined with GMNet. Specifically, my game determines a users control set in real time based on the game mode and number of controllers plugged; as a result, I was able to extend the variables that control this functionality to have an additional set of commands to receive controls from the network instead. Remote players update their inputs from the network, and the game state is updated using client side prediction until there's a discrepancy in game states. Each step, the game state is saved locally into a ds_list, and then base64_encoded into a separate ds_list. The base64_encode states are compared, and when there's a mismatch, both games return to the last synchronized state and rerun the game with the correct inputs for each step.

I'm currently building a 2D fighter called Evolver. I completed the code for the versus mode early last month, and the engines for the metroidvania campaign and survival modes are working and tested. As a result, I'm now trying to implement the GGPO netcode (wiki) which uses a frame rollback method to manage networking. Rather than setup a mutual server, GGPO sets up individual sessions on all hosts and simply sends each players inputs to all other players connected to the session. So, all players are essentially running a local game where only the opponents' inputs are networked.

As you may have deduced, this could and would lead to issues with synchronization, thus the rollbacks. GGPO manages desyncs through input prediction and rollback frames. This is dependent on the "gamestate" being "purely functional" meaning the game most move forward at a fixed rate, and for any give game state and inputs, advancing the game by exactly 1 frame must have identical results for each client which is simple enough given GM:S's use of steps.

GGPO runs the session through a C++ object of the class GGPOSession, and that's where my trouble begins. I don't imagine there's any way to use a C++ object in GM:S, so my thinking is to have GM:S start C++ program (which I’ll call BackNet) that initializes the GGPOSession in the background, and then have BackNet pass information to GM:S via buffers. That said, I'm not sure if this is possible or the best method of implementing the GGPO framework.

The download link to the SDK is dead on http://ggpo.org/download, but I got a copy from Tony Cannon (free, non profit license. For profit license is $1,000 I believe, and Tony's email is in docs) which includes a guide and example for a very simple C program he included called Vector War. You can download it from my onedrive, here.
 
Last edited:

Drell

Member
Maybe you can write a dll? What exactly is wrong with just building it in gm itself?


In this example script that comes in the SDK guide, the GGPOSession, GGPOErrorCode, and GGPOSessionCallbacks objects are initialized, and then the callback functions are filled because it is required with the way GGPO is setup. Then, ggpo_start_session is used to start the actual networking session. These objects are defined in the DLL, but as far as I know, GM:S can't initialize a C++ object. I was thinking that using a second DLL to manage BackNet instead of a separate exe could work, but I don't know if that's possible or if it would be better.

Additionally it would seem that once the GGPOSession was initialized, it could be managed from game maker by passing the pointer addresses to GM:S through a buffer. That is, I could maybe do:
Code:
ggpo_start_session(ggpo,cb,"Evolver",2,buffer_sizeof(buffer_u8),8001);
after implementing ggpo_start_session as a function in GM:S, where GM:S's ggpo and cb variables are passed in from the dll as &ggpo and &cb respectively. And, if that's possible, the same logic should work for the rest of the DLL implementation as far as I can tell. However, in the example included with the SDK, the gamestate seems to be separate from GGPO, and I'm not sure if that's possible with GM:S or how to go about it if it is. Unlike the example, my gamestate has dozens if not hundreds of factors to consider, but it's not clear to me whether I should be creating my own rollback function within GM:S, or if somehow the DLL can rollback GM:S/my code with it's own architecture. Either way, it would seem that at the very least, the GGPOSession, etc, needs to be initialized outside of GM:S (via BackNet) even if I handle the functions within the game script.
 
Last edited:
Top