private PinMame(PinMameAudioFormat audioFormat, int sampleRate, string vpmPath) { Logger.Info($"PinMame - audioFormat={audioFormat}, sampleRate={sampleRate}, vpmPath={vpmPath}"); var path = vpmPath ?? GetVpmPath(); if (path == null) { throw new ArgumentException("Could not determine VPM path. Either install VPinMAME or provide it manually.", nameof(vpmPath)); } if (!Directory.Exists(path)) { throw new ArgumentException($"Could not find VPM path - {path} does not exist.", nameof(vpmPath)); } _config = new PinMameApi.PinmameConfig { audioFormat = (PinMameApi.PinmameAudioFormat)audioFormat, sampleRate = sampleRate, vpmPath = path + Path.DirectorySeparatorChar, onStateUpdated = OnStateUpdatedCallback, onDisplayAvailable = OnDisplayAvailableCallback, onDisplayUpdated = OnDisplayUpdatedCallback, onAudioAvailable = OnAudioAvailableCallback, onAudioUpdated = OnAudioUpdatedCallback, onMechAvailable = OnMechAvailableCallback, onMechUpdated = OnMechUpdatedCallback, onSolenoidUpdated = OnSolenoidUpdatedCallback, onConsoleDataUpdated = OnConsoleDataUpdatedCallback, isKeyPressed = IsKeyPressedFunction, }; PinMameApi.PinmameSetConfig(ref _config); }
private void OnDisplayAvailableCallback(int index, int displayCount, ref PinMameApi.PinmameDisplayLayout displayLayoutRef) { var displayLayout = new PinMameDisplayLayout(displayLayoutRef, PinMameApi.PinmameGetHardwareGen()); Logger.Trace($"OnDisplayAvailableCallback - index={index}, displayCount={displayCount}, displayLayout={displayLayout}"); OnDisplayAvailable?.Invoke(index, displayCount, displayLayout); }
/// <summary> /// Continues a paused game. /// </summary> /// <exception cref="InvalidOperationException"></exception> public void Continue() { Logger.Info("Continue"); var status = PinMameApi.PinmamePause(0); if (status != PinMameApi.PinmameStatus.OK) { throw new InvalidOperationException($"Unable to continue game, status={status}"); } }
/// <summary> /// Starts a new game. <p/> /// /// When the game has successfully started, the <see cref="OnGameStarted"/> event is triggered. /// </summary> /// <param name="gameName">Name of the game, e.g. "tz_94h"</param> /// <exception cref="InvalidOperationException">If there is already a game running.</exception> /// <exception cref="ArgumentException">If the game name is invalid.</exception> public void StartGame(string gameName) { Logger.Info("StartGame"); RunningGame = gameName; var status = PinMameApi.PinmameRun(gameName); if (status != PinMameApi.PinmameStatus.OK) { throw new InvalidOperationException($"Unable to start game, status={status}"); } }
/// <summary> /// Returns an array of all changed GIs since the last call. /// /// The returned array contains pairs, where the first element is the /// GI number, and the second element the value. /// </summary> public PinMameLampInfo[] GetChangedGIs() { var num = PinMameApi.PinmameGetChangedGIs(_changedGIs); PinMameLampInfo[] array = new PinMameLampInfo[num]; for (int index = 0; index < num; index++) { array[index] = new PinMameLampInfo(_changedGIs[index * 2], _changedGIs[(index * 2) + 1]); } return(array); }
/// <summary> /// Retrieves a game by game name. /// </summary> /// <exception cref="InvalidOperationException">If the configuration has not been set or the game name is not found.</exception> public PinMameGame GetGame(string name) { Logger.Info($"GetGame: name={name}"); PinMameGame game = null; var status = PinMameApi.PinmameGetGame(name, gamePtr => { game = new PinMameGame(gamePtr); }); if (status != PinMameApi.PinmameStatus.OK) { throw new InvalidOperationException($"Unable to get game, name={name}, status={status}"); } return(game); }
private void OnStateUpdatedCallback(int state) { Logger.Debug($"OnStateUpdatedCallback - state={state}"); if (state == 1) { _changedLamps = new int[PinMameApi.PinmameGetMaxLamps() * 2]; _changedGIs = new int[PinMameApi.PinmameGetMaxGIs() * 2]; OnGameStarted?.Invoke(); } else { OnGameEnded?.Invoke(); RunningGame = null; } }
/// <summary> /// Retrieves all games found in roms folder. Clones array will not be populated. /// </summary> /// <exception cref="InvalidOperationException">If the configuration has not been set.</exception> public IEnumerable <PinMameGame> GetFoundGames() { var games = new List <PinMameGame>(); var status = PinMameApi.PinmameGetGames(gamePtr => { var game = new PinMameGame(gamePtr); if (game.RomFound) { games.Add(game); } }); if (status != PinMameApi.PinmameStatus.OK) { throw new InvalidOperationException($"Unable to get games, status={status}"); } return(games); }
/// <summary> /// Sets the configuration of a given mech. /// </summary> /// <param name="mechNo">Mech number</param> /// <param name="config">Mech configuration. A null value will remove the mech.</param> public void SetMech(int mechNo, PinMameMechConfig?config = null) { PinMameApi.PinmameStatus status; if (config.HasValue) { var tmpConfig = (PinMameMechConfig)config; var mechConfig = new PinMameApi.PinmameMechConfig(); mechConfig.sol1 = tmpConfig.Sol1; mechConfig.sol2 = tmpConfig.Sol2; mechConfig.type = (int)tmpConfig.Type; mechConfig.length = tmpConfig.Length; mechConfig.steps = tmpConfig.Steps; mechConfig.initialPos = tmpConfig.InitialPos; mechConfig.sw = new PinMameApi.PinmameMechSwitchConfig[PinMameApi.MaxMechSwitches]; var index = 0; foreach (var switchConfig in tmpConfig.SwitchList) { mechConfig.sw[index].swNo = switchConfig.SwNo; mechConfig.sw[index].startPos = switchConfig.StartPos; mechConfig.sw[index].endPos = switchConfig.EndPos; mechConfig.sw[index].pulse = switchConfig.Pulse; index++; } status = PinMameApi.PinmameSetMech(mechNo, ref mechConfig); } else { status = PinMameApi.PinmameSetMech(mechNo, IntPtr.Zero); } if (status != PinMameApi.PinmameStatus.OK) { throw new InvalidOperationException($"Unable to set mech, status={status}"); } }
/// <summary> /// Returns if the HandleMechanics option is enabled or disabled. /// </summary> public bool GetHandleMechanics() => PinMameApi.PinmameGetHandleMechanics() == 1;
/// <summary> /// Returns an array of all changed GIs since the last call. /// /// The returned array contains pairs, where the first element is the /// GI number, and the second element the value. /// </summary> public Span <int> GetChangedGIs() { var num = PinMameApi.PinmameGetChangedGIs(_changedGIs); return(_changedGIs.AsSpan().Slice(0, num * 2)); }
/// <summary> /// Returns the maximal supported number of Mechs. /// </summary> /// <returns>Number of Mechs</returns> public int GetMaxMechs() => PinMameApi.PinmameGetMaxMechs();
/// <summary> /// Returns the maximal supported number of lamps. /// </summary> /// <returns>Number of lamps</returns> public int GetMaxLamps() => PinMameApi.PinmameGetMaxLamps();
/// <summary> /// Returns the maximal supported number of GIs. /// </summary> /// <returns>Number of GIs</returns> public int GetMaxGIs() => PinMameApi.PinmameGetMaxGIs();
/// <summary> /// Returns the state of a given switch. /// </summary> /// <param name="slot">Slot number of the switch</param> /// <returns>Value of the switch</returns> public bool GetSwitch(int slot) => PinMameApi.PinmameGetSwitch(slot) != 0;
/// <summary> /// Sets the state of a given switch. /// </summary> /// <param name="slot">Slot number of the switch</param> /// <param name="state">New value of the switch</param> public void SetSwitch(int slot, bool state) => PinMameApi.PinmameSetSwitch(slot, state ? 1 : 0);
/// <summary> /// Sets the value of a given mech. /// </summary> /// <param name="mechNo">Mech number</param> /// <param name="value">New value of the mech</param> public void SetMech(int mechNo, int value) => PinMameApi.PinmameSetMech(mechNo, value);
/// <summary> /// Returns the value of a given mech. /// </summary> /// <param name="mechNo">Mech number</param> /// <returns>Value of the mech</returns> public int GetMech(int mechNo) => PinMameApi.PinmameGetMech(mechNo);
/// <summary> /// Stops a game. /// </summary> public void StopGame() { Logger.Info("StopGame"); PinMameApi.PinmameStop(); }
/// <summary> /// Returns if the HandleKeyboard option is enabled or disabled. /// </summary> public bool GetHandleKeyboard() => PinMameApi.PinmameGetHandleKeyboard() == 1;
/// <summary> /// Resets a game. /// </summary> public void ResetGame() { Logger.Info("ResetGame"); PinMameApi.PinmameReset(); }
/// <summary> /// Enables or disables the HandleMechanics option. /// </summary> /// <param name="handleMechanics">New value of the HandleMechanics option.</param> public void SetHandleMechanics(bool handleMechanics) => PinMameApi.PinmameSetHandleMechanics(handleMechanics ? 1 : 0);
/// <summary> /// Enables or disables the HandleKeyboard option. /// </summary> /// <param name="handleKeyboard">New value of the HandleKeyboard flag.</param> public void SetHandleKeyboard(bool handleKeyboard) => PinMameApi.PinmameSetHandleKeyboard(handleKeyboard ? 1 : 0);
/// <summary> /// Returns the HandleMechanics value. /// </summary> public int GetHandleMechanics() => PinMameApi.PinmameGetHandleMechanics();
/// <summary> /// Sets the HandleMechanics option. /// </summary> /// <param name="handleMechanics">New value of the HandleMechanics option.</param> public void SetHandleMechanics(int handleMechanics) => PinMameApi.PinmameSetHandleMechanics(handleMechanics);