@@ -84,6 +84,8 @@ public GamelogicEngineLamp[] AvailableLamps {
84
84
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
85
85
private static readonly Color Tint = new Color ( 1 , 0.18f , 0 ) ;
86
86
87
+ private readonly Queue < Action > _dispatchQueue = new Queue < Action > ( ) ;
88
+
87
89
private void Start ( )
88
90
{
89
91
UpdateCaches ( ) ;
@@ -96,7 +98,7 @@ public void OnInit(Player player, TableApi tableApi, BallManager ballManager)
96
98
OnLampChanged ? . Invoke ( this , new LampEventArgs ( lamp . Id , 0 ) ) ;
97
99
}
98
100
99
- _pinMame = PinMame . PinMame . Instance ( ) ;
101
+ _pinMame = PinMame . PinMame . Instance ( 48000 , @"C:\Games\Visual Pinball\VPinMAME" ) ;
100
102
_pinMame . OnGameStarted += GameStarted ;
101
103
_pinMame . OnGameEnded += GameEnded ;
102
104
_pinMame . OnDisplayUpdate += DisplayUpdated ;
@@ -117,6 +119,31 @@ private void GameStarted(object sender, EventArgs e)
117
119
_isRunning = true ;
118
120
}
119
121
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
+
120
147
private void DisplayUpdated ( object sender , EventArgs e , int index , IntPtr framePtr , PinMameDisplayLayout displayLayout )
121
148
{
122
149
if ( ( displayLayout . type & PinMameDisplayType . DMD ) > 0 ) {
@@ -135,7 +162,12 @@ private void UpdateSegDisp(int index, PinMameDisplayLayout displayLayout, IntPtr
135
162
private void UpdateDmd ( int index , PinMameDisplayLayout displayLayout , IntPtr framePtr )
136
163
{
137
164
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
+
139
171
_sizeAnnounced = true ;
140
172
_frameBuffer = new byte [ displayLayout . width * displayLayout . height ] ;
141
173
}
@@ -151,25 +183,21 @@ private void UpdateDmd(int index, PinMameDisplayLayout displayLayout, IntPtr fra
151
183
}
152
184
}
153
185
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 ) ) ) ;
161
189
}
162
-
163
- return ( _pinMame . GetHardwareGen ( ) & ( PinMameHardwareGen . SAM | PinMameHardwareGen . SPA ) ) > 0
164
- ? DmdMapSam
165
- : DmdMapGts ;
166
190
}
167
191
168
192
private void SolenoidChanged ( object sender , EventArgs e , int internalId , bool isActive )
169
193
{
170
194
if ( _coils . ContainsKey ( internalId ) ) {
171
195
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
+ }
173
201
174
202
} else {
175
203
Logger . Warn ( $ "[PinMAME] <= coil UNMAPPED { internalId } : { isActive } ") ;
@@ -199,25 +227,6 @@ public void SendInitialSwitches()
199
227
}
200
228
}
201
229
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
-
221
230
private void UpdateCaches ( )
222
231
{
223
232
if ( _game == null ) {
@@ -257,6 +266,18 @@ public void Switch(string id, bool isClosed)
257
266
}
258
267
}
259
268
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
+
260
281
private static DisplayFrameFormat GetDisplayType ( PinMameDisplayType dp )
261
282
{
262
283
switch ( dp ) {
0 commit comments