@@ -84,6 +84,8 @@ public GamelogicEngineLamp[] AvailableLamps {
8484 private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
8585 private static readonly Color Tint = new Color ( 1 , 0.18f , 0 ) ;
8686
87+ private readonly Queue < Action > _dispatchQueue = new Queue < Action > ( ) ;
88+
8789 private void Start ( )
8890 {
8991 UpdateCaches ( ) ;
@@ -96,7 +98,7 @@ public void OnInit(Player player, TableApi tableApi, BallManager ballManager)
9698 OnLampChanged ? . Invoke ( this , new LampEventArgs ( lamp . Id , 0 ) ) ;
9799 }
98100
99- _pinMame = PinMame . PinMame . Instance ( ) ;
101+ _pinMame = PinMame . PinMame . Instance ( 48000 , @"C:\Games\Visual Pinball\VPinMAME" ) ;
100102 _pinMame . OnGameStarted += GameStarted ;
101103 _pinMame . OnGameEnded += GameEnded ;
102104 _pinMame . OnDisplayUpdate += DisplayUpdated ;
@@ -117,6 +119,31 @@ private void GameStarted(object sender, EventArgs e)
117119 _isRunning = true ;
118120 }
119121
122+ private void Update ( )
123+ {
124+ if ( _pinMame == null || ! _isRunning ) {
125+ return ;
126+ }
127+
128+ lock ( _dispatchQueue ) {
129+ while ( _dispatchQueue . Count > 0 ) {
130+ _dispatchQueue . Dequeue ( ) . Invoke ( ) ;
131+ }
132+ }
133+
134+ // lamps
135+ var changedLamps = _pinMame . GetChangedLamps ( ) ;
136+ for ( var i = 0 ; i < changedLamps . Length ; i += 2 ) {
137+ var internalId = changedLamps [ i ] ;
138+ var val = changedLamps [ i + 1 ] ;
139+
140+ if ( _lamps . ContainsKey ( internalId ) ) {
141+ //Logger.Info($"[PinMAME] <= lamp {id}: {val}");
142+ OnLampChanged ? . Invoke ( this , new LampEventArgs ( _lamps [ internalId ] . Id , val ) ) ;
143+ }
144+ }
145+ }
146+
120147 private void DisplayUpdated ( object sender , EventArgs e , int index , IntPtr framePtr , PinMameDisplayLayout displayLayout )
121148 {
122149 if ( ( displayLayout . type & PinMameDisplayType . DMD ) > 0 ) {
@@ -135,7 +162,12 @@ private void UpdateSegDisp(int index, PinMameDisplayLayout displayLayout, IntPtr
135162 private void UpdateDmd ( int index , PinMameDisplayLayout displayLayout , IntPtr framePtr )
136163 {
137164 if ( ! _sizeAnnounced ) {
138- OnDisplaysAvailable ? . Invoke ( this , new AvailableDisplays ( new DisplayConfig ( DisplayDmd , displayLayout . width , displayLayout . height ) ) ) ;
165+ lock ( _dispatchQueue ) {
166+ _dispatchQueue . Enqueue ( ( ) =>
167+ OnDisplaysAvailable ? . Invoke ( this , new AvailableDisplays (
168+ new DisplayConfig ( DisplayDmd , displayLayout . width , displayLayout . height ) ) ) ) ;
169+ }
170+
139171 _sizeAnnounced = true ;
140172 _frameBuffer = new byte [ displayLayout . width * displayLayout . height ] ;
141173 }
@@ -151,25 +183,21 @@ private void UpdateDmd(int index, PinMameDisplayLayout displayLayout, IntPtr fra
151183 }
152184 }
153185
154- OnDisplayFrame ? . Invoke ( this , new DisplayFrameData ( DisplayDmd , GetDisplayType ( displayLayout . type ) , _frameBuffer ) ) ;
155- }
156-
157- private Dictionary < byte , byte > GetMap ( PinMameDisplayLayout displayLayout )
158- {
159- if ( displayLayout . depth == 2 ) {
160- return DmdMap2Bit ;
186+ lock ( _dispatchQueue ) {
187+ _dispatchQueue . Enqueue ( ( ) => OnDisplayFrame ? . Invoke ( this ,
188+ new DisplayFrameData ( DisplayDmd , GetDisplayType ( displayLayout . type ) , _frameBuffer ) ) ) ;
161189 }
162-
163- return ( _pinMame . GetHardwareGen ( ) & ( PinMameHardwareGen . SAM | PinMameHardwareGen . SPA ) ) > 0
164- ? DmdMapSam
165- : DmdMapGts ;
166190 }
167191
168192 private void SolenoidChanged ( object sender , EventArgs e , int internalId , bool isActive )
169193 {
170194 if ( _coils . ContainsKey ( internalId ) ) {
171195 Logger . Info ( $ "[PinMAME] <= coil { _coils [ internalId ] . Id } ({ internalId } ): { isActive } | { _coils [ internalId ] . Description } ") ;
172- OnCoilChanged ? . Invoke ( this , new CoilEventArgs ( _coils [ internalId ] . Id , isActive ) ) ;
196+
197+ lock ( _dispatchQueue ) {
198+ _dispatchQueue . Enqueue ( ( ) =>
199+ OnCoilChanged ? . Invoke ( this , new CoilEventArgs ( _coils [ internalId ] . Id , isActive ) ) ) ;
200+ }
173201
174202 } else {
175203 Logger . Warn ( $ "[PinMAME] <= coil UNMAPPED { internalId } : { isActive } ") ;
@@ -199,25 +227,6 @@ public void SendInitialSwitches()
199227 }
200228 }
201229
202- private void Update ( )
203- {
204- if ( _pinMame == null || ! _isRunning ) {
205- return ;
206- }
207-
208- // lamps
209- var changedLamps = _pinMame . GetChangedLamps ( ) ;
210- for ( var i = 0 ; i < changedLamps . Length ; i += 2 ) {
211- var internalId = changedLamps [ i ] ;
212- var val = changedLamps [ i + 1 ] ;
213-
214- if ( _lamps . ContainsKey ( internalId ) ) {
215- //Logger.Info($"[PinMAME] <= lamp {id}: {val}");
216- OnLampChanged ? . Invoke ( this , new LampEventArgs ( _lamps [ internalId ] . Id , val ) ) ;
217- }
218- }
219- }
220-
221230 private void UpdateCaches ( )
222231 {
223232 if ( _game == null ) {
@@ -257,6 +266,18 @@ public void Switch(string id, bool isClosed)
257266 }
258267 }
259268
269+
270+ private Dictionary < byte , byte > GetMap ( PinMameDisplayLayout displayLayout )
271+ {
272+ if ( displayLayout . depth == 2 ) {
273+ return DmdMap2Bit ;
274+ }
275+
276+ return ( _pinMame . GetHardwareGen ( ) & ( PinMameHardwareGen . SAM | PinMameHardwareGen . SPA ) ) > 0
277+ ? DmdMapSam
278+ : DmdMapGts ;
279+ }
280+
260281 private static DisplayFrameFormat GetDisplayType ( PinMameDisplayType dp )
261282 {
262283 switch ( dp ) {
0 commit comments