@@ -46,12 +46,17 @@ void MultiplayerControllerDeinit(MultiplayerController* controller) {
4646 MutexDeinit (& controller -> lockstepMutex );
4747}
4848
49+ static void _onFrameDoneMult (struct mCoreThread * context ) {
50+ mCoreThreadPauseFromThread (context );
51+ }
52+
4953bool MultiplayerControllerAttachGame (MultiplayerController * controller , struct CoreController * game ) {
5054 if (controller -> attached >= MAX_PLAYERS ) {
5155 return false;
5256 }
5357
5458 game -> multiplayer = controller ;
59+ game -> threadContext .frameCallback = _onFrameDoneMult ;
5560
5661 if (controller -> platform == mPLATFORM_NONE ) {
5762 controller -> platform = game -> core -> platform (game -> core );
@@ -137,34 +142,23 @@ void MultiplayerControllerRunFrame(MultiplayerController* controller) {
137142 struct CoreController * cc = controller -> players [i ];
138143 if (!cc ) continue ;
139144 struct mCoreThread * thread = & cc -> threadContext ;
140- struct mCoreSync * sync = & thread -> impl -> sync ;
141-
142- if (mCoreThreadIsPaused (thread )) {
143- mCoreThreadUnpause (thread );
144- }
145-
146- MutexLock (& sync -> videoFrameMutex );
147- sync -> videoFramePending = 0 ;
148- // Only the first core blocks at the end of its frame.
149- // This avoids deadlocks during hardware link handshakes at the end of frames.
150- sync -> videoFrameWait = (i == 0 );
151- ConditionWake (& sync -> videoFrameRequiredCond );
152- MutexUnlock (& sync -> videoFrameMutex );
145+
146+ mCoreThreadUnpause (thread );
153147 }
154148}
155149
156150void MultiplayerControllerWaitFrame (MultiplayerController * controller ) {
157- if (controller -> attached == 0 || ! controller -> players [ 0 ] ) return ;
151+ if (controller -> attached == 0 ) return ;
158152
159- // We only wait for the first player to finish its frame.
160- // Lockstep will naturally throttle the others to its speed.
161- struct CoreController * cc = controller -> players [0 ];
162- struct mCoreThread * thread = & cc -> threadContext ;
163- struct mCoreSync * sync = & thread -> impl -> sync ;
153+ for (int i = 0 ; i < controller -> attached ; ++ i ) {
154+ struct CoreController * cc = controller -> players [i ];
155+ if (!cc ) continue ;
156+ struct mCoreThread * thread = & cc -> threadContext ;
164157
165- MutexLock (& sync -> videoFrameMutex );
166- while (sync -> videoFramePending == 0 && mCoreThreadIsActive (thread )) {
167- ConditionWait (& sync -> videoFrameAvailableCond , & sync -> videoFrameMutex );
158+ MutexLock (& thread -> impl -> stateMutex );
159+ while (thread -> impl -> state != mTHREAD_PAUSED && mCoreThreadIsActive (thread )) {
160+ ConditionWait (& thread -> impl -> stateOffThreadCond , & thread -> impl -> stateMutex );
161+ }
162+ MutexUnlock (& thread -> impl -> stateMutex );
168163 }
169- MutexUnlock (& sync -> videoFrameMutex );
170164}
0 commit comments