1818using System . Collections . Generic ;
1919using System . Linq ;
2020using NLog ;
21+ using PinMame ;
2122using UnityEngine ;
2223using VisualPinball . Engine . Game . Engines ;
2324using VisualPinball . Unity ;
@@ -76,6 +77,7 @@ public GamelogicEngineLamp[] AvailableLamps {
7677
7778 private const string DisplayDmd = "dmd" ;
7879
80+ private bool _isRunning ;
7981 private bool _sizeAnnounced ;
8082
8183 private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
@@ -94,10 +96,62 @@ public void OnInit(Player player, TableApi tableApi, BallManager ballManager)
9496 }
9597
9698 _pinMame = PinMame . PinMame . Instance ( ) ;
97- _pinMame . StartGame ( romId , showConsole : true ) ;
99+ _pinMame . OnGameStarted += GameStarted ;
100+ _pinMame . OnGameEnded += GameEnded ;
101+ _pinMame . OnDisplayUpdate += DisplayUpdated ;
102+ _pinMame . OnSolenoid += SolenoidChanged ;
103+ _pinMame . StartGame ( romId ) ;
98104 _player = player ;
99105 }
100106
107+ private void GameStarted ( object sender , EventArgs e )
108+ {
109+ Logger . Info ( $ "[PinMAME] Game started.") ;
110+ _isRunning = true ;
111+ }
112+
113+ private void DisplayUpdated ( object sender , EventArgs e , int index , IntPtr framePtr , PinMameDisplayLayout displayLayout )
114+ {
115+ if ( ( displayLayout . type & PinMameDisplayType . DMD ) > 0 ) {
116+ UpdateDmd ( index , displayLayout , framePtr ) ;
117+ } else {
118+ UpdateSegDisp ( index , displayLayout , framePtr ) ;
119+ }
120+ }
121+
122+ private void UpdateSegDisp ( int index , PinMameDisplayLayout displayLayout , IntPtr framePtr )
123+ {
124+
125+ }
126+
127+
128+ private void UpdateDmd ( int index , PinMameDisplayLayout displayLayout , IntPtr framePtr )
129+ {
130+ if ( ! _sizeAnnounced ) {
131+ OnDisplaysAvailable ? . Invoke ( this , new AvailableDisplays ( new DisplayConfig ( DisplayDmd , displayLayout . width , displayLayout . height ) ) ) ;
132+ _sizeAnnounced = true ;
133+ }
134+ OnDisplayFrame ? . Invoke ( this , new DisplayFrameData ( DisplayDmd , GetDisplayType ( displayLayout . type ) , framePtr ) ) ;
135+
136+ }
137+
138+ private void SolenoidChanged ( object sender , EventArgs e , int internalId , bool isActive )
139+ {
140+ if ( _coils . ContainsKey ( internalId ) ) {
141+ Logger . Info ( $ "[PinMAME] <= coil { _coils [ internalId ] . Id } ({ internalId } ): { isActive } | { _coils [ internalId ] . Description } ") ;
142+ OnCoilChanged ? . Invoke ( this , new CoilEventArgs ( _coils [ internalId ] . Id , isActive ) ) ;
143+
144+ } else {
145+ Logger . Warn ( $ "[PinMAME] <= coil UNMAPPED { internalId } : { isActive } ") ;
146+ }
147+ }
148+
149+ private void GameEnded ( object sender , EventArgs e )
150+ {
151+ Logger . Info ( $ "[PinMAME] Game ended.") ;
152+ _isRunning = false ;
153+ }
154+
101155 public void SendInitialSwitches ( )
102156 {
103157 var switches = _player . SwitchStatusesClosed ;
@@ -117,25 +171,10 @@ public void SendInitialSwitches()
117171
118172 private void Update ( )
119173 {
120- if ( _pinMame == null || ! _pinMame . IsRunning ) {
174+ if ( _pinMame == null || ! _isRunning ) {
121175 return ;
122176 }
123177
124- // coils
125- var changedCoils = _pinMame . GetChangedSolenoids ( ) ;
126- for ( var i = 0 ; i < changedCoils . Length ; i += 2 ) {
127- var internalId = changedCoils [ i ] ;
128- var val = changedCoils [ i + 1 ] ;
129-
130- if ( _coils . ContainsKey ( internalId ) ) {
131- Logger . Info ( $ "[PinMAME] <= coil { _coils [ internalId ] . Id } ({ internalId } ): { val } | { _coils [ internalId ] . Description } ") ;
132- OnCoilChanged ? . Invoke ( this , new CoilEventArgs ( _coils [ internalId ] . Id , val == 1 ) ) ;
133-
134- } else {
135- Logger . Warn ( $ "[PinMAME] <= coil UNMAPPED { internalId } : { val } ") ;
136- }
137- }
138-
139178 // lamps
140179 var changedLamps = _pinMame . GetChangedLamps ( ) ;
141180 for ( var i = 0 ; i < changedLamps . Length ; i += 2 ) {
@@ -147,20 +186,8 @@ private void Update()
147186 OnLampChanged ? . Invoke ( this , new LampEventArgs ( _lamps [ internalId ] . Id , val ) ) ;
148187 }
149188 }
150-
151- // dmd
152- if ( _pinMame . NeedsDmdUpdate ( ) ) {
153- if ( ! _sizeAnnounced ) {
154- var dim = _pinMame . GetDmdDimensions ( ) ;
155- OnDisplaysAvailable ? . Invoke ( this , new AvailableDisplays (
156- new DisplayConfig ( DisplayDmd , DisplayType . Dmd2PinMame , dim . Width , dim . Height ) ) ) ;
157- _sizeAnnounced = true ;
158- }
159- OnDisplayFrame ? . Invoke ( this , new DisplayFrameData ( DisplayDmd , _pinMame . GetDmdPixels ( ) ) ) ;
160- }
161189 }
162190
163-
164191 private void UpdateCaches ( )
165192 {
166193 if ( _game == null ) {
@@ -182,7 +209,12 @@ private void UpdateCaches()
182209
183210 private void OnDestroy ( )
184211 {
185- _pinMame ? . StopGame ( ) ;
212+ if ( _pinMame != null ) {
213+ _pinMame . StopGame ( ) ;
214+ _pinMame . OnGameStarted -= GameStarted ;
215+ _pinMame . OnGameEnded -= GameEnded ;
216+ _pinMame . OnDisplayUpdate -= DisplayUpdated ;
217+ }
186218 }
187219
188220 public void Switch ( string id , bool isClosed )
@@ -194,28 +226,52 @@ public void Switch(string id, bool isClosed)
194226 Logger . Error ( $ "[PinMAME] Unknown switch \" { id } \" .") ;
195227 }
196228 }
197- }
198229
199- // internal readonly struct DisplayKey : IEquatable<DisplayKey>
200- // {
201- // private readonly int _width;
202- // private readonly int _height;
203- // private readonly int _bitLength;
204- //
205- // public DisplayKey(int width, int height, int bitLength)
206- // {
207- // _width = width;
208- // _height = height;
209- // _bitLength = bitLength;
210- // }
211- //
212- // public override bool Equals(object obj) => obj is DisplayKey other && Equals(other);
213- //
214- // public bool Equals(DisplayKey other)
215- // {
216- // return _width == other._width && _height == other._height && _bitLength == other._bitLength;
217- // }
218- //
219- // public override int GetHashCode() => (_width, _height, _bitLength).GetHashCode();
220- // }
230+ private static DisplayFrameFormat GetDisplayType ( PinMameDisplayType dp )
231+ {
232+ switch ( dp ) {
233+ case PinMameDisplayType . SEG16 :
234+ break ;
235+ case PinMameDisplayType . SEG16R :
236+ break ;
237+ case PinMameDisplayType . SEG10 :
238+ break ;
239+ case PinMameDisplayType . SEG9 :
240+ break ;
241+ case PinMameDisplayType . SEG8 :
242+ break ;
243+ case PinMameDisplayType . SEG8D :
244+ break ;
245+ case PinMameDisplayType . SEG7 :
246+ break ;
247+ case PinMameDisplayType . SEG87 :
248+ break ;
249+ case PinMameDisplayType . SEG87F :
250+ break ;
251+ case PinMameDisplayType . SEG98 :
252+ break ;
253+ case PinMameDisplayType . SEG98F :
254+ break ;
255+ case PinMameDisplayType . SEG7S :
256+ break ;
257+ case PinMameDisplayType . SEG7SC :
258+ break ;
259+ case PinMameDisplayType . SEG16S :
260+ break ;
261+ case PinMameDisplayType . DMD :
262+ return DisplayFrameFormat . Dmd2PinMame ;
263+
264+ case PinMameDisplayType . VIDEO :
265+ break ;
266+ case PinMameDisplayType . SEG16N :
267+ break ;
268+ case PinMameDisplayType . SEG16D :
269+ break ;
270+ default :
271+ throw new ArgumentOutOfRangeException ( nameof ( dp ) , dp , null ) ;
272+ }
273+
274+ throw new NotImplementedException ( "only dmd frames supported for now" ) ;
275+ }
276+ }
221277}
0 commit comments