Skip to content

Commit 6f19642

Browse files
committed
fix: Dispatch callbacks to main thread.
1 parent 23e87d9 commit 6f19642

File tree

1 file changed

+54
-33
lines changed

1 file changed

+54
-33
lines changed

VisualPinball.Engine.PinMAME.Unity/Runtime/PinMameGamelogicEngine.cs

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)