Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kaillera Support #569

Closed
Ownasaurus opened this issue Aug 20, 2015 · 18 comments
Closed

Kaillera Support #569

Ownasaurus opened this issue Aug 20, 2015 · 18 comments

Comments

@Ownasaurus
Copy link

Greetings,

Is there any interest in having kaillera support in the main release rather than having side projects such as project64k which use a very old base version?

I just started working on adding kaillera support to the 2.2 release yesterday for fun. I was just wondering if I should keep this to myself as a side project or if I should share the code with the main developers.

Also, if I am looking to insert code to synchronize input between clients for netplay purposes (again, kaillera protocol), where would you recommend inserting such code? I am looking for a function that runs regularly - such as once per frame.

I apologize if this isn't posted in the correct section. It is my first time using github and I do not know if there is a better place for questions.

Thanks,
Owna

@cxd4
Copy link
Contributor

cxd4 commented Aug 21, 2015

can't remember but is Kaillera open-source? Ideally there should be a way to implement a reliable, portable NetPlay that can be managed on different platforms, as well as 32- vs. 64-bit etc.

I think the current stage of having a compatible NetPlay into Project64 officially is to better the "Fixed Audio Timing" feature. You may have noticed this core option in RDB settings--it's designed to regulate all events and results of the emulation to be reproducible to the exact same time. Though I don't know if Kaillera or some other custom implementation of NetPlay was the desired end result.

@Ownasaurus
Copy link
Author

Hi cxd4,

Yes - Kaillera is an open-source protocol with a few publicly available implementations including mame32k. Even "Ownaclient" is somewhere out there - which is an old kailleraclient.dll that I updated a few years ago. In this protocol, it is the emulator's job to import one of several functions from a DLL and invoke them when appropriate. I have almost everything in place except for perhaps the most important function call - the call which synchronizes input between clients. Below, please find an excerpt from the API:

 kailleraModifyPlayValues:
 You must call this method at every frame after you retrieved values from your input devices.
 This method will record/bufferize the values you send in and will manage to mix them with 
 the other players. 


 Basically, each players sends his values and receive all players values concatened.

 e.g:
 t   - player 1 sends "867F"            - player 2 sends "964F"
 t+1 - player 1 receives "867F964F"     - player 2 receives "867F964F"

Certainly having reproducible and accurate results is a desired emulation result. What is very interesting to me is that Project64k (core 1.3) was released in 2003 when - to my knowledge - the code was not even publicly available. I wonder if somebody is in touch with its developer Hotquik or has any information that will save me re-inventing the wheel! However I imagine that if it was possible with Project 64 1.4, it should be no problem now!

What do you think?

  • Owna

@JunielKatarn
Copy link
Contributor

From what I see in the Kaillera website, the protocol is NOT open source, but it does provide a client API. Might be worth a shot.

@Ownasaurus
Copy link
Author

You might have to help me out with the official definition of "open source." The original developers never released the source, but it has since been unofficially documented and understood:

 Documentation: http://tinyurl.com/npffjwg
 Open source kaillera server: http://sourceforge.net/projects/emulinker/files/emulinker-kaillera-server/
 Open source kaillera client: https://code.google.com/p/p2pkaillera/

So I'm honestly not sure if it is technically considered open source, but it is certainly well-understood at this point. I personally have done both client-side and server-side development but have never done the code to interface with an emulator until now.

As long as there is no reason that kaillera support has been purposely left out of the main release, I would be happy to share my code once it is working. Just need to find the optimal locations to

  1. read the input to send out
  2. receive the input and update locally as necessary
  • Owna

@Ownasaurus
Copy link
Author

To be specific, I am interested to know: if I want get the state of every button on the controller, which is the best way:

Access the RawData?
CONTROL * Controllers = g_Plugins->Control()->PluginControllers();
DWORD tempData = Controllers[0].RawData;

Get the BUTTONS?
g_Plugins->Control()->GetKeys(0, &Keys);

And should I be doing this at the PIF level (CPifRam) or is there a more high level alternative?

Thanks,
Owna

@cxd4
Copy link
Contributor

cxd4 commented Aug 21, 2015

Controllers[0].RawData; is just a Boolean that indicates whether the controller plugin set up the first controller to process over raw data or to use the high-level core functions internal to Project64's built-in method.

I don't know anything about the PIF commands.

Get the BUTTONS?
g_Plugins->Control()->GetKeys(0, &Keys);

Not sure if this helps, but here is part of the GetKeys plugin function I implemented:

EXPORT void CALL GetKeys(int Control, BUTTONS * Keys)
{
    u16 buttons;

    assert(Control < MAX_CONTROLLERS);
    assert(Keys != NULL);

    buttons = controllers[Control].Value & 0x0000FFFFul;
 // ...

Important to remember that in PJ64's case the 16-bit button mask is byte-swapped.

@Ownasaurus
Copy link
Author

Ah silly me - my bad. Thanks for the info cxd4! I will look into it.

  • Owna

@Ownasaurus
Copy link
Author

Seems like a good place to insert kaillera input code would be in CN64System::RefreshScreen in a loop that seems to read the input:

for (int Control = 0; Control < 4; Control++)
{   
        g_Plugins->Control()->GetKeys(Control,&Keys);
        m_Buttons[Control] = Keys.Value;
}

Is this good form? Will update as progress is made.

@Ownasaurus
Copy link
Author

I am embarrassed to admit that while I have no trouble reading the controller input (can get from many different functions / data structures), I am having a lot of trouble writing / overriding the controller input. As a test, I am trying to take player1's input and replicate it for player2. However, modifying any of the higher level data structures seems to have no effect. For example, modifying m_Buttons seems to have no effect on the execution.

Do I need to manually edit the appropriate section of the PIF to "simulate" controller input?

Thanks for your help,
Owna

@cxd4
Copy link
Contributor

cxd4 commented Aug 22, 2015

No idea. I mostly just work with controllers from within the controller plugins, not the Project64 core internals which also I know less of.

@project64
Copy link
Owner

in void CN64System::RefreshScreen()

you have the code:
if (g_Plugins->Control()->GetKeys)
{
BUTTONS Keys;
memset(&Keys,0,sizeof(Keys));

    for (int Control = 0; Control < 4; Control++)
    {   
        g_Plugins->Control()->GetKeys(Control,&Keys);
        m_Buttons[Control] = Keys.Value;
    }
}

this gets all the states of the controller, do the sync here for updating players controllers, use m_buttons and update it with the defailts of the other controllers.

@Ownasaurus
Copy link
Author

Thanks for your reply Zilmar. It seemed to do nothing when I modified m_Buttons in that region, so I gave up with that part of the code. if I literally commented it out, controllers still worked. BUT now I see it seems to depend whether RawData is enabled or not. if RawData is unchecked, i do seem to be able to insert code there!

And I almost had it working to at the PIF level too! (input works over kaillera but out of sync at the moment)

  • Owna

@cxd4
Copy link
Contributor

cxd4 commented Aug 22, 2015

RawData always seemed to mess things up with Kaillera on 1964 emulator. I usually had to disable it in N-Rage, 1964Input, whatever input plugin I was using. Otherwise the sync was horrible.

It probably has something to do with the fact that RawData requires processing from within the plugin, while disabling RawData uses the core stuff to the host emulator executable which is probably more thread-safe or whatever.

@AmbientMalice
Copy link
Contributor

Kaillera strikes me as a somewhat flawed technology since all it does is send button data. Any random variable will throw the whole shebang out -- for example, trying to play a game with AI characters or any sort of "random" outcomes.

Unless I'm misunderstanding things.

@Ownasaurus
Copy link
Author

You are correct that it just sends buttonData. If the emulator emulates consistently though, i think it works well (maybe random seed based off number of frames since power on?).

But you are 100% correct that kaillera is a nearly obsolete protocol. I have some friends who are working on a new netplay protocol that includes joining games in progress and spectating.

@cxd4
Copy link
Contributor

cxd4 commented Aug 23, 2015

Might have helped if that French guy who invented Kaillera didn't vanish off the ass of the Earth in 2002, never to be seen again.

@Ownasaurus
Copy link
Author

I just played smash bros for about 10 min over kaillera using core 2.2 and it didn't desync with items on. it did desync when i selected a random CPU though.

Will do more and post findings, but it's moving in a great direction!

@Ownasaurus
Copy link
Author

Well thank you everybody for all of your help. I now have a working (alpha... still some bugs) version of kaillera based off of the 2.2 release. I am a complete git newbie, but I tried to host it on my account. So, all future discussion will be there I suppose. Thanks again, and if it works out well, I hope it can eventually be pulled into the main codebase :)

  • Owna

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants