public MovieZone(IMovie movie, IEmulator emulator, ToolManager tools, int start, int length, string key = "") { _emulator = emulator; _tools = tools; var lg = movie.LogGeneratorInstance(); lg.SetSource(Global.MovieSession.MovieControllerAdapter); _targetController = new Bk2ControllerAdapter { Definition = _emulator.ControllerDefinition }; _targetController.LatchFromSource(_targetController); // Reference and create all buttons if (key == "") { key = lg.GenerateLogKey(); } key = key.Replace("LogKey:", "").Replace("#", ""); key = key.Substring(0, key.Length - 1); _inputKey = key; Length = length; _log = new string[length]; // Get a IController that only contains buttons in key. string[] keys = key.Split('|'); var d = new ControllerDefinition(); foreach (var k in keys) { if (_emulator.ControllerDefinition.BoolButtons.Contains(k)) { d.BoolButtons.Add(k); } else { d.FloatControls.Add(k); int rangeIndex = _emulator.ControllerDefinition.FloatControls.IndexOf(k); d.FloatRanges.Add(_emulator.ControllerDefinition.FloatRanges[rangeIndex]); } } _controller = new Bk2ControllerAdapter { Definition = d }; var logGenerator = new Bk2LogEntryGenerator(""); logGenerator.SetSource(_controller); logGenerator.GenerateLogEntry(); // Reference and create all buttons. string movieKey = logGenerator.GenerateLogKey().Replace("LogKey:", "").Replace("#", ""); movieKey = movieKey.Substring(0, movieKey.Length - 1); if (key == movieKey) { for (int i = 0; i < length; i++) { _log[i] = movie.GetInputLogEntry(i + start); } } else { for (int i = 0; i < length; i++) { _controller.LatchFromSource(movie.GetInputState(i + start)); _log[i] = logGenerator.GenerateLogEntry(); } } }
public ControllerAdapter(LibNymaCore core, IList <string> config) { var ret = new ControllerDefinition { Name = "Mednafen Controller" }; var finalDevices = new List <string>(); var numPorts = core.GetNumPorts(); if (numPorts > MAX_PORTS) { throw new InvalidOperationException($"Too many input ports"); } for (uint port = 0, devByteStart = 0; port < numPorts; port++, devByteStart += MAX_PORT_DATA) { var portInfo = *core.GetPort(port); var deviceName = port < config.Count ? config[(int)port] : portInfo.DefaultDeviceShortName; finalDevices.Add(deviceName); var devices = Enumerable.Range(0, (int)portInfo.NumDevices) .Select(i => new { Index = (uint)i, Device = *core.GetDevice(port, (uint)i) }) .ToList(); var device = devices.FirstOrDefault(a => a.Device.ShortName == deviceName); if (device == null) { Console.WriteLine($"Warn: unknown controller device {deviceName}"); device = devices.FirstOrDefault(a => a.Device.ShortName == portInfo.DefaultDeviceShortName); if (device == null) { throw new InvalidOperationException($"Fail: unknown controller device {portInfo.DefaultDeviceShortName}"); } } var deviceInfo = device.Device; if (deviceInfo.ByteLength > MAX_PORT_DATA) { throw new InvalidOperationException($"Input device {deviceInfo.ShortName} uses more than {MAX_PORT_DATA} bytes"); } var category = portInfo.FullName + " - " + deviceInfo.FullName; var inputs = Enumerable.Range(0, (int)deviceInfo.NumInputs) .Select(i => new { Index = i, Data = *core.GetInput(port, device.Index, (uint)i) }) .OrderBy(a => a.Data.ConfigOrder); foreach (var input in inputs) { var inputInfo = input.Data; var bitSize = (int)inputInfo.BitSize; var bitOffset = (int)inputInfo.BitOffset; var byteStart = devByteStart + bitOffset / 8; bitOffset %= 8; var name = $"P{port + 1} {inputInfo.Name}"; switch (inputInfo.Type) { case LibNymaCore.InputType.PADDING: { break; } case LibNymaCore.InputType.BUTTON: case LibNymaCore.InputType.BUTTON_CAN_RAPID: { // var data = *core.GetButton(port, device.Index, (uint)input.Index); // TODO: Wire up data.ExcludeName ret.BoolButtons.Add(name); _thunks.Add((c, b) => { if (c.IsPressed(name)) { b[byteStart] |= (byte)(1 << bitOffset); } }); break; } case LibNymaCore.InputType.SWITCH: { var data = *core.GetSwitch(port, device.Index, (uint)input.Index); var zzhacky = (int)data.DefaultPosition; // TODO: Possibly bulebutton for 2 states? ret.AxisControls.Add(name); ret.AxisRanges.Add(new ControllerDefinition.AxisRange( 0, (int)data.DefaultPosition, (int)data.NumPositions - 1)); _thunks.Add((c, b) => { // HACK: Silently discard this until bizhawk fixes its shit // var val = (int)Math.Round(c.AxisValue(name)); var val = zzhacky; b[byteStart] |= (byte)(val << bitOffset); }); break; } case LibNymaCore.InputType.AXIS: { // var data = core.GetAxis(port, device.Index, (uint)input.Index); ret.AxisControls.Add(name); ret.AxisRanges.Add(new ControllerDefinition.AxisRange( 0, 0x8000, 0xffff, (inputInfo.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0 )); _thunks.Add((c, b) => { var val = (ushort)Math.Round(c.AxisValue(name)); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case LibNymaCore.InputType.AXIS_REL: { // var data = core.GetAxis(port, device.Index, (uint)input.Index); ret.AxisControls.Add(name); ret.AxisRanges.Add(new ControllerDefinition.AxisRange( -0x8000, 0, 0x7fff, (inputInfo.Flags & LibNymaCore.AxisFlags.INVERT_CO) != 0 )); _thunks.Add((c, b) => { var val = (short)Math.Round(c.AxisValue(name)); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case LibNymaCore.InputType.POINTER_X: { throw new Exception("TODO: Axis ranges are ints????"); // ret.AxisControls.Add(name); // ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, 0.5, 1)); // break; } case LibNymaCore.InputType.POINTER_Y: { throw new Exception("TODO: Axis ranges are ints????"); // ret.AxisControls.Add(name); // ret.AxisRanges.Add(new ControllerDefinition.AxisRange(0, 0.5, 1, true)); // break; } // TODO: wire up statuses to something (not controller, of course) default: throw new NotImplementedException($"Unimplemented button type {inputInfo.Type}"); } ret.CategoryLabels[name] = category; } } Definition = ret; finalDevices.Add(null); Devices = finalDevices.ToArray(); }
public void HardReset() { cpu = new MOS6502X(); cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory); cpu.BCD_Enabled = false; cpu.OnExecFetch = ExecFetch; ppu = new PPU(this); ram = new byte[0x800]; CIRAM = new byte[0x800]; // wire controllers // todo: allow changing this ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); // set controller definition first time only if (ControllerDefinition == null) { ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition()); ControllerDefinition.Name = "NES Controller"; // controls other than the deck ControllerDefinition.BoolButtons.Add("Power"); ControllerDefinition.BoolButtons.Add("Reset"); if (Board is FDS) { var b = Board as FDS; ControllerDefinition.BoolButtons.Add("FDS Eject"); for (int i = 0; i < b.NumSides; i++) { ControllerDefinition.BoolButtons.Add("FDS Insert " + i); } } } // don't replace the magicSoundProvider on reset, as it's not needed // if (magicSoundProvider != null) magicSoundProvider.Dispose(); // set up region switch (_display_type) { case Common.DisplayType.PAL: apu = new APU(this, apu, true); ppu.region = PPU.Region.PAL; CoreComm.VsyncNum = 50; CoreComm.VsyncDen = 1; cpuclockrate = 1662607; cpu_sequence = cpu_sequence_PAL; _display_type = DisplayType.PAL; break; case Common.DisplayType.NTSC: apu = new APU(this, apu, false); ppu.region = PPU.Region.NTSC; CoreComm.VsyncNum = 39375000; CoreComm.VsyncDen = 655171; cpuclockrate = 1789773; cpu_sequence = cpu_sequence_NTSC; break; // this is in bootgod, but not used at all case Common.DisplayType.DENDY: apu = new APU(this, apu, false); ppu.region = PPU.Region.Dendy; CoreComm.VsyncNum = 50; CoreComm.VsyncDen = 1; cpuclockrate = 1773448; cpu_sequence = cpu_sequence_NTSC; _display_type = DisplayType.DENDY; break; default: throw new Exception("Unknown displaytype!"); } if (magicSoundProvider == null) { magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate); } BoardSystemHardReset(); //check fceux's PowerNES and FCEU_MemoryRand function for more information: //relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack for (int i = 0; i < 0x800; i++) { if ((i & 4) != 0) { ram[i] = 0xFF; } else { ram[i] = 0x00; } } SetupMemoryDomains(); //in this emulator, reset takes place instantaneously cpu.PC = (ushort)(ReadMemory(0xFFFC) | (ReadMemory(0xFFFD) << 8)); cpu.P = 0x34; cpu.S = 0xFD; }
public MovieZone(string fileName) { if (!File.Exists(fileName)) { return; } string[] readText = File.ReadAllLines(fileName); // If the LogKey contains buttons/controls not accepted by the emulator, // tell the user and display the macro's controller name and player count _inputKey = readText[0]; Bk2LogEntryGenerator lg = Global.MovieSession.LogGeneratorInstance() as Bk2LogEntryGenerator; lg.SetSource(Global.MovieSession.MovieControllerAdapter); string key = lg.GenerateLogKey(); key = key.Replace("LogKey:", "").Replace("#", ""); key = key.Substring(0, key.Length - 1); string[] emuKeys = key.Split('|'); string[] macroKeys = _inputKey.Split('|'); for (int i = 0; i < macroKeys.Length; i++) { if (!emuKeys.Contains(macroKeys[i])) { System.Windows.Forms.MessageBox.Show("The selected macro is not compatible with the current emulator core." + "\nMacro controller: " + readText[1] + "\nMacro player count: " + readText[2], "Error"); return; } } // Settings string[] settings = readText[3].Split(','); Overlay = Convert.ToBoolean(settings[0]); Replace = Convert.ToBoolean(settings[1]); _log = new string[readText.Length - 4]; readText.ToList().CopyTo(4, _log, 0, _log.Length); Length = _log.Length; Start = 0; Name = Path.GetFileNameWithoutExtension(fileName); // Adapters targetController = new Bk2ControllerAdapter(); targetController.Definition = Global.Emulator.ControllerDefinition; targetController.LatchFromSource(targetController); // Reference and create all buttons string[] keys = _inputKey.Split('|'); ControllerDefinition d = new ControllerDefinition(); for (int i = 0; i < keys.Length; i++) { if (Global.Emulator.ControllerDefinition.BoolButtons.Contains(keys[i])) { d.BoolButtons.Add(keys[i]); } else { d.FloatControls.Add(keys[i]); } } controller = new Bk2ControllerAdapter { Definition = d }; }
public Bk2ControllerDefinition(ControllerDefinition source) : base(source) { }
/// <summary>don't do this</summary> public void ForceType(ControllerDefinition newType) => Definition = newType;
public SnesSaveController(ControllerDefinition def) { this.def = def; }
public ControllerNES() { ControllerDefFragment = new("(NES Controller fragment)") { BoolButtons = Buttons.OrderBy(x => _buttonOrdinals[x]).ToList() }; }
public ControllerNES(bool famicomP2) { if (famicomP2) { ControllerDefFragment = new("(NES Controller fragment)") { BoolButtons = FamicomP2Buttons.Where(static s => s is not null).OrderBy(x => _buttonOrdinals[x]).ToList() };
public ActionDefinition(ControllerDefinition controller, MethodInfo method) { Controller = controller; Method = method; Signature = HashSignature(Method); }
private static Expression FindAndInvokeActions(Expression request, Expression pathStr, PropertyInfo pathIndexer, int i, ControllerDefinition controller) { var filler = new String(new char[i]); var controllerVar = Expression.Variable(controller.Type); var runAction = GenerateSwitches(request, pathStr, pathIndexer, i, controller.Actions, x => filler + x.Name, (request2, pathStrI, pathIndexerI, lastI, d) => { return(Expression.Condition(Expression.Equal(Expression.PropertyOrField(pathStrI, nameof(StringSegment.Length)), Expression.Constant(lastI)), BuildActionInvocation(d, request, controllerVar), ResponseNotFound)); }); foreach (var mw in controller.InstanceMiddleware.Reverse()) { runAction = Expression.Coalesce(Expression.Call(controllerVar, mw, request), runAction); } Expression ret = Expression.Block( new[] { controllerVar }, Expression.Assign(controllerVar, Expression.New(controller.Type)), // TODO: match regex runAction); foreach (var mw in controller.StaticMiddleware.Reverse()) { ret = Expression.Coalesce(Expression.Call(mw, request), ret); } return(ret); }
public void HardReset() { cpu = new MOS6502X <CpuLink>(new CpuLink(this)) { BCD_Enabled = false }; ppu = new PPU(this); ram = new byte[0x800]; CIRAM = new byte[0x800]; // wire controllers // todo: allow changing this ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); // set controller definition first time only if (ControllerDefinition == null) { ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition()) { Name = "NES Controller" }; // controls other than the deck ControllerDefinition.BoolButtons.Add("Power"); ControllerDefinition.BoolButtons.Add("Reset"); if (Board is FDS b) { ControllerDefinition.BoolButtons.Add("FDS Eject"); for (int i = 0; i < b.NumSides; i++) { ControllerDefinition.BoolButtons.Add("FDS Insert " + i); } } if (_isVS) { ControllerDefinition.BoolButtons.Add("Insert Coin P1"); ControllerDefinition.BoolButtons.Add("Insert Coin P2"); ControllerDefinition.BoolButtons.Add("Service Switch"); } } // Add in the reset timing axis for subneshawk if (using_reset_timing && ControllerDefinition.Axes.Count == 0) { ControllerDefinition.AddAxis("Reset Cycle", 0.RangeTo(500000), 0); } // don't replace the magicSoundProvider on reset, as it's not needed // if (magicSoundProvider != null) magicSoundProvider.Dispose(); // set up region switch (_display_type) { case DisplayType.PAL: apu = new APU(this, apu, true); ppu.region = PPU.Region.PAL; cpuclockrate = 1662607; VsyncNum = cpuclockrate * 2; VsyncDen = 66495; cpu_sequence = cpu_sequence_PAL; _display_type = DisplayType.PAL; ClockRate = 5320342.5; break; case DisplayType.NTSC: apu = new APU(this, apu, false); ppu.region = PPU.Region.NTSC; cpuclockrate = 1789773; VsyncNum = cpuclockrate * 2; VsyncDen = 59561; cpu_sequence = cpu_sequence_NTSC; ClockRate = 5369318.1818181818181818181818182; break; // this is in bootgod, but not used at all case DisplayType.Dendy: apu = new APU(this, apu, false); ppu.region = PPU.Region.Dendy; cpuclockrate = 1773448; VsyncNum = cpuclockrate; VsyncDen = 35464; cpu_sequence = cpu_sequence_NTSC; _display_type = DisplayType.Dendy; ClockRate = 5320342.5; break; default: throw new Exception("Unknown displaytype!"); } blip.SetRates((uint)cpuclockrate, 44100); BoardSystemHardReset(); // apu has some specific power up bahaviour that we will emulate here apu.NESHardReset(); if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any()) { for (int i = 0; i < 0x800; i++) { ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count]; } } else { // check fceux's PowerNES and FCEU_MemoryRand function for more information: // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack for (int i = 0; i < 0x800; i++) { if ((i & 4) != 0) { ram[i] = 0xFF; } else { ram[i] = 0x00; } } } SetupMemoryDomains(); // some boards cannot have specific values in RAM upon initialization // Let's hard code those cases here // these will be defined through the gameDB exclusively for now. if (cart.GameInfo != null) { if (cart.GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" || // Camerica Golden 5 cart.GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" || // Camerica Golden 5 cart.GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23" // Camerica Pegasus 4-in-1 ) { ram[0x701] = 0xFF; } if (cart.GameInfo.Hash == "68ABE1E49C9E9CCEA978A48232432C252E5912C0") // Dancing Blocks { ram[0xEC] = 0; ram[0xED] = 0; } if (cart.GameInfo.Hash == "00C50062A2DECE99580063777590F26A253AAB6B") // Silva Saga { for (int i = 0; i < Board.Wram.Length; i++) { Board.Wram[i] = 0xFF; } } } }
public SimpleController(ControllerDefinition definition) => Definition = definition;
public IList <ControllerDefinition> RewriteControllers(CSharpCompilation compiler) { var controllers = new Dictionary <string, ControllerDefinition>(); foreach (var tree in compiler.SyntaxTrees.Where(x => !x.FilePath.EndsWith(".generated.cs"))) { // if syntaxtree has errors, skip code generation if (tree.GetDiagnostics().Any(x => x.Severity == DiagnosticSeverity.Error)) { continue; } // this first part, finds all the controller classes, modifies them and saves the changes var controllerRewriter = new ControllerRewriter(compiler); SyntaxNode newNode; try { newNode = controllerRewriter.Visit(tree.GetRoot()); } catch { // If roslyn can't get the root of the tree, just continue to the next item continue; } // save the controller nodes from each visit to pass to the generator foreach (var controllerNode in controllerRewriter.MvcControllerClassNodes) { var cNamespace = controllerNode.FirstAncestorOrSelf <NamespaceDeclarationSyntax>().Name.ToFullString().Trim(); var cSymbol = compiler.GetSemanticModel(tree).GetDeclaredSymbol(controllerNode); var cFullName = cNamespace + "." + cSymbol.Name; if (controllers.ContainsKey(cFullName)) { controllers[cFullName].FilePaths.Add(tree.FilePath); continue; } var cAreaName = _controllerGenerator.GetControllerArea(cSymbol); controllers[cFullName] = new ControllerDefinition { Namespace = cNamespace, Name = cSymbol.Name.TrimEnd("Controller"), Area = cAreaName, Symbol = cSymbol, FilePaths = new List <string> { tree.FilePath }, }; } if (!newNode.IsEquivalentTo(tree.GetRoot())) { // node has changed, update syntaxtree and persist to file // Updating the new syntax tree with the syntax options from the original tree // Seems like the new syntax tree might be generated with a different language version than the original. (see #79) var newTree = newNode.SyntaxTree.WithRootAndOptions(newNode.SyntaxTree.GetRoot(), tree.Options); compiler = compiler.ReplaceSyntaxTree(tree, newTree); _filePersistService.WriteFile(newNode, tree.FilePath); } } return(controllers.Values.ToList()); }
static Pizza() { _gbDefinition = CreateControllerDefinition(1); _sgbDefinition = CreateControllerDefinition(4); }
public static ControllerDefinition AddZapper(this ControllerDefinition def, string nameFormat) => def.AddXYPair(nameFormat, AxisPairOrientation.RightAndUp, 0.RangeTo(255), 128, 0.RangeTo(239), 120); //TODO verify direction against hardware
public MovieZone(IMovie movie, IEmulator emulator, ToolManager tools, IMovieSession movieSession, int start, int length, string key = "") { _emulator = emulator; _tools = tools; _movieSession = movieSession; var lg = movie.LogGeneratorInstance(movieSession.MovieController); _targetController = movieSession.GenerateMovieController(); _targetController.SetFrom(_targetController); // Reference and create all buttons if (key == "") { key = lg.GenerateLogKey(); } key = key.Replace("LogKey:", "").Replace("#", ""); key = key.Substring(0, key.Length - 1); _inputKey = key; Length = length; _log = new string[length]; // Get a IController that only contains buttons in key. string[] keys = key.Split('|'); var d = new ControllerDefinition(); foreach (var k in keys) { if (_emulator.ControllerDefinition.BoolButtons.Contains(k)) { d.BoolButtons.Add(k); } else { d.Axes.Add(k, _emulator.ControllerDefinition.Axes[k]); } } _controller = movieSession.GenerateMovieController(d); var logGenerator = movieSession.Movie.LogGeneratorInstance(_controller); logGenerator.GenerateLogEntry(); // Reference and create all buttons. string movieKey = logGenerator.GenerateLogKey().Replace("LogKey:", "").Replace("#", ""); movieKey = movieKey.Substring(0, movieKey.Length - 1); if (key == movieKey) { for (int i = 0; i < length; i++) { _log[i] = movie.GetInputLogEntry(i + start); } } else { for (int i = 0; i < length; i++) { _controller.SetFrom(movie.GetInputState(i + start)); _log[i] = logGenerator.GenerateLogEntry(); } } }
public async Task Run(string projectPath) { var projectRoot = Path.GetDirectoryName(projectPath); // Load the project and check for compilation errors var workspace = MSBuildWorkspace.Create(); DumpMsBuildAssemblies("clean workspace"); var project = await workspace.OpenProjectAsync(projectPath); DumpMsBuildAssemblies("project loaded"); if (workspace.Diagnostics.Count > 0) { var foundErrors = false; foreach (var diag in workspace.Diagnostics) { Console.Error.WriteLine($" {diag.Kind}: {diag.Message}"); if (diag.Kind == Microsoft.CodeAnalysis.WorkspaceDiagnosticKind.Failure) { foundErrors = true; } } if (foundErrors) { return; } } // Prep the project Compilation object, and process the Controller public methods list var compilation = await project.GetCompilationAsync() as CSharpCompilation; SyntaxNodeHelpers.PopulateControllerClassMethodNames(compilation); // Analyse the controllers in the project (updating them to be partial), as well as locate all the view files var controllers = _controllerRewriter.RewriteControllers(compilation); var allViewFiles = _viewLocators.SelectMany(x => x.Find(projectRoot)); // Assign view files to controllers foreach (var views in allViewFiles.GroupBy(v => new { v.AreaName, v.ControllerName })) { var controller = controllers .Where(c => string.Equals(c.Name, views.Key.ControllerName, StringComparison.OrdinalIgnoreCase)) .Where(c => string.Equals(c.Area, views.Key.AreaName, StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (controller == null) { controllers.Add(controller = new ControllerDefinition { Area = views.Key.AreaName, Name = views.Key.ControllerName, }); } foreach (var view in views) { controller.Views.Add(view); } } // Generate mappings for area names, to avoid clashes with controller names var areaMap = GenerateAreaMap(controllers); foreach (var controller in controllers.Where(a => !string.IsNullOrEmpty(a.Area))) { controller.AreaKey = areaMap[controller.Area]; } // Generate the R4Mvc.generated.cs file _generatorService.Generate(projectRoot, controllers); }
public SnesSaveController() { this.def = null; }
public AutofireController(ControllerDefinition definition) { On = Global.Config.AutofireOn < 1 ? 0 : Global.Config.AutofireOn; Off = Global.Config.AutofireOff < 1 ? 0 : Global.Config.AutofireOff; _type = definition; }
public ControllerAdapter( List<NPortInfoT> allPorts, IDictionary<int, string> config, Func<string, string> overrideName, bool hasCds, ref SystemInfo systemInfo, HashSet<string> hiddenPorts, string controllerDeckName) { var ret = new ControllerDefinition { Name = controllerDeckName, CategoryLabels = { { "Power", "System" }, { "Reset", "System" }, { "Previous Disk", "System" }, { "Next Disk", "System" }, } }; var finalDevices = new List<string>(); var switchPreviousFrame = new List<byte>(); for (int port = 0, devByteStart = 0; port < allPorts.Count; port++) { var portInfo = allPorts[port]; var deviceName = config.ContainsKey(port) ? config[port] : portInfo.DefaultDeviceShortName; finalDevices.Add(deviceName); if (hiddenPorts.Contains(portInfo.ShortName)) continue; var devices = portInfo.Devices; var device = devices.FirstOrDefault(a => a.ShortName == deviceName); if (device == null) { Console.WriteLine($"Warn: unknown controller device {deviceName}"); device = devices.FirstOrDefault(a => a.ShortName == portInfo.DefaultDeviceShortName); if (device == null) throw new InvalidOperationException($"Fail: unknown controller device {portInfo.DefaultDeviceShortName}"); } ActualPortData.Add(new PortResult { Port = portInfo, Device = device }); var deviceInfo = device; var category = portInfo.FullName + " - " + deviceInfo.FullName; var inputs = deviceInfo.Inputs .OrderBy(a => a.ConfigOrder); foreach (var input in inputs) { if (input.Type == InputType.Padding) continue; var bitSize = (int)input.BitSize; var bitOffset = (int)input.BitOffset; var byteStart = devByteStart + bitOffset / 8; bitOffset %= 8; var baseName = input.Name; if (baseName != null) baseName = overrideName(baseName); var name = input.Type == InputType.ResetButton ? "Reset" : $"P{port + 1} {baseName}"; switch (input.Type) { case InputType.ResetButton: case InputType.Button: case InputType.ButtonCanRapid: { // var data = inputInfo.Extra.AsButton(); // TODO: Wire up data.ExcludeName if (input.Type != InputType.ResetButton) { ret.BoolButtons.Add(name); ret.CategoryLabels[name] = category; } _thunks.Add((c, b) => { if (c.IsPressed(name)) b[byteStart] |= (byte)(1 << bitOffset); }); break; } case InputType.Switch: { var data = input.Extra.AsSwitch(); if (data.Positions.Count > 8) throw new NotImplementedException("Need code changes to support Mdfn switch with more than 8 positions"); // fake switches as a series of push downs that select each state // imagine the "gear" selector on a Toyota Prius var si = switchPreviousFrame.Count; // [si]: position of this switch on the previous frame switchPreviousFrame.Add((byte)data.DefaultPosition); // [si + 1]: bit array of the previous state of each selector button switchPreviousFrame.Add(0); var names = data.Positions.Select(p => $"{name}: Set {p.Name}").ToArray(); if (!input.Name.StartsWith("AF ") && !input.Name.EndsWith(" AF") && !input.Name.StartsWith("Autofire ")) // hack: don't support some devices { foreach (var n in names) { { ret.BoolButtons.Add(n); ret.CategoryLabels[n] = category; } } } _thunks.Add((c, b) => { var val = _switchPreviousFrame[si]; var allOldPressed = _switchPreviousFrame[si + 1]; byte allNewPressed = 0; for (var i = 0; i < names.Length; i++) { var mask = (byte)(1 << i); var oldPressed = allOldPressed & mask; var newPressed = c.IsPressed(names[i]) ? mask : (byte)0; if (newPressed > oldPressed) val = (byte)i; allNewPressed |= newPressed; } _switchPreviousFrame[si] = val; _switchPreviousFrame[si + 1] = allNewPressed; b[byteStart] |= (byte)(val << bitOffset); }); break; } case InputType.Axis: { var data = input.Extra.AsAxis(); var fullName = $"{name} {overrideName(data.NameNeg)} / {overrideName(data.NamePos)}"; ret.AddAxis(fullName, 0.RangeTo(0xFFFF), 0x8000, (input.Flags & AxisFlags.InvertCo) != 0); ret.CategoryLabels[fullName] = category; _thunks.Add((c, b) => { var val = c.AxisValue(fullName); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case InputType.AxisRel: { var data = input.Extra.AsAxis(); var fullName = $"{name} {input.Extra.AsAxis().NameNeg} / {input.Extra.AsAxis().NamePos}"; // TODO: Mednafen docs say this range should be [-32768, 32767], and inspecting the code // reveals that a 16 bit value is read, but using anywhere near this full range makes // PCFX mouse completely unusable. Maybe this is some TAS situation where average users // will want a 1/400 multiplier on sensitivity but TASers might want one frame screenwide movement? ret.AddAxis(fullName, (-127).RangeTo(127), 0, (input.Flags & AxisFlags.InvertCo) != 0); ret.CategoryLabels[fullName] = category; _thunks.Add((c, b) => { var val = c.AxisValue(fullName); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case InputType.PointerX: { // I think the core expects to be sent some sort of 16 bit integer, but haven't investigated much ret.AddAxis(name, systemInfo.PointerOffsetX.RangeTo(systemInfo.PointerScaleX), systemInfo.PointerOffsetX); _thunks.Add((c, b) => { var val = c.AxisValue(name); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case InputType.PointerY: { // I think the core expects to be sent some sort of 16 bit integer, but haven't investigated much ret.AddAxis(name, systemInfo.PointerOffsetY.RangeTo(systemInfo.PointerScaleY), systemInfo.PointerOffsetY); _thunks.Add((c, b) => { var val = c.AxisValue(name); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case InputType.ButtonAnalog: { ret.AddAxis(name, 0.RangeTo(0xFFFF), 0); ret.CategoryLabels[name] = category; _thunks.Add((c, b) => { var val = c.AxisValue(name); b[byteStart] = (byte)val; b[byteStart + 1] = (byte)(val >> 8); }); break; } case InputType.Status: // TODO: wire up statuses to something (not controller, of course) break; default: { throw new NotImplementedException($"Unimplemented button type {input.Type}"); } } } devByteStart += (int)deviceInfo.ByteLength; if (devByteStart > MAX_INPUT_DATA) throw new NotImplementedException($"More than {MAX_INPUT_DATA} input data bytes"); } ret.BoolButtons.Add("Power"); ret.BoolButtons.Add("Reset"); if (hasCds) { ret.BoolButtons.Add("Previous Disk"); ret.BoolButtons.Add("Next Disk"); } Definition = ret; finalDevices.Add(null); Devices = finalDevices.ToArray(); _switchPreviousFrame = switchPreviousFrame.ToArray(); }
/// <summary>don't do this</summary> public void ForceType(ControllerDefinition newtype) { _type = newtype; }
public MovieZone(IMovie movie, int start, int length, string key = "") { var lg = Global.MovieSession.LogGeneratorInstance() as Bk2LogEntryGenerator; lg.SetSource(Global.MovieSession.MovieControllerAdapter); targetController = new Bk2ControllerAdapter(); targetController.Definition = Global.Emulator.ControllerDefinition; targetController.LatchFromSource(targetController); // Reference and create all buttons if (key == "") { key = lg.GenerateLogKey(); } key = key.Replace("LogKey:", "").Replace("#", ""); key = key.Substring(0, key.Length - 1); _inputKey = key; Length = length; _log = new string[length]; // Get a IController that only contains buttons in key. string[] keys = key.Split('|'); var d = new ControllerDefinition(); for (int i = 0; i < keys.Length; i++) { if (Global.Emulator.ControllerDefinition.BoolButtons.Contains(keys[i])) { d.BoolButtons.Add(keys[i]); } else { d.FloatControls.Add(keys[i]); } } controller = new Bk2ControllerAdapter { Definition = d }; var logGenerator = new Bk2LogEntryGenerator(""); logGenerator.SetSource(controller); logGenerator.GenerateLogEntry(); // Reference and create all buttons. string movieKey = logGenerator.GenerateLogKey().Replace("LogKey:", "").Replace("#", ""); movieKey = movieKey.Substring(0, movieKey.Length - 1); if (key == movieKey) { for (int i = 0; i < length; i++) { _log[i] = movie.GetInputLogEntry(i + start); } } else { for (int i = 0; i < length; i++) { controller.LatchFromSource(movie.GetInputState(i + start)); _log[i] = logGenerator.GenerateLogEntry(); } } }
public void RecreateMovieController(ControllerDefinition definition) { MovieController = new Bk2Controller(definition); }
public void HardReset() { cpu = new MOS6502X(); cpu.SetCallbacks(ReadMemory, ReadMemory, PeekMemory, WriteMemory); cpu.BCD_Enabled = false; cpu.OnExecFetch = ExecFetch; ppu = new PPU(this); ram = new byte[0x800]; CIRAM = new byte[0x800]; // wire controllers // todo: allow changing this ControllerDeck = ControllerSettings.Instantiate(ppu.LightGunCallback); // set controller definition first time only if (ControllerDefinition == null) { ControllerDefinition = new ControllerDefinition(ControllerDeck.GetDefinition()); ControllerDefinition.Name = "NES Controller"; // controls other than the deck ControllerDefinition.BoolButtons.Add("Power"); ControllerDefinition.BoolButtons.Add("Reset"); if (Board is FDS) { var b = Board as FDS; ControllerDefinition.BoolButtons.Add("FDS Eject"); for (int i = 0; i < b.NumSides; i++) { ControllerDefinition.BoolButtons.Add("FDS Insert " + i); } } if (_isVS) { ControllerDefinition.BoolButtons.Add("Insert Coin P1"); ControllerDefinition.BoolButtons.Add("Insert Coin P2"); ControllerDefinition.BoolButtons.Add("Service Switch"); } } // don't replace the magicSoundProvider on reset, as it's not needed // if (magicSoundProvider != null) magicSoundProvider.Dispose(); // set up region switch (_display_type) { case Common.DisplayType.PAL: apu = new APU(this, apu, true); ppu.region = PPU.Region.PAL; VsyncNum = 50; VsyncDen = 1; cpuclockrate = 1662607; cpu_sequence = cpu_sequence_PAL; _display_type = DisplayType.PAL; break; case Common.DisplayType.NTSC: apu = new APU(this, apu, false); ppu.region = PPU.Region.NTSC; VsyncNum = 39375000; VsyncDen = 655171; cpuclockrate = 1789773; cpu_sequence = cpu_sequence_NTSC; break; // this is in bootgod, but not used at all case Common.DisplayType.Dendy: apu = new APU(this, apu, false); ppu.region = PPU.Region.Dendy; VsyncNum = 50; VsyncDen = 1; cpuclockrate = 1773448; cpu_sequence = cpu_sequence_NTSC; _display_type = DisplayType.Dendy; break; default: throw new Exception("Unknown displaytype!"); } if (magicSoundProvider == null) { magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate); } BoardSystemHardReset(); // apu has some specific power up bahaviour that we will emulate here apu.NESHardReset(); if (SyncSettings.InitialWRamStatePattern != null && SyncSettings.InitialWRamStatePattern.Any()) { for (int i = 0; i < 0x800; i++) { ram[i] = SyncSettings.InitialWRamStatePattern[i % SyncSettings.InitialWRamStatePattern.Count]; } } else { // check fceux's PowerNES and FCEU_MemoryRand function for more information: // relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack for (int i = 0; i < 0x800; i++) { if ((i & 4) != 0) { ram[i] = 0xFF; } else { ram[i] = 0x00; } } } SetupMemoryDomains(); // some boards cannot have specific values in RAM upon initialization // Let's hard code those cases here // these will be defined through the gameDB exclusively for now. if (cart.DB_GameInfo != null) { if (cart.DB_GameInfo.Hash == "60FC5FA5B5ACCAF3AEFEBA73FC8BFFD3C4DAE558" || // Camerica Golden 5 cart.DB_GameInfo.Hash == "BAD382331C30B22A908DA4BFF2759C25113CC26A" || // Camerica Golden 5 cart.DB_GameInfo.Hash == "40409FEC8249EFDB772E6FFB2DCD41860C6CCA23" // Camerica Pegasus 4-in-1 ) { ram[0x701] = 0xFF; } if (cart.DB_GameInfo.Hash == "68ABE1E49C9E9CCEA978A48232432C252E5912C0") // Dancing Blocks { ram[0xEC] = 0; ram[0xED] = 0; } } }
public IMovieController GenerateMovieController(ControllerDefinition definition = null) { // TODO: expose Movie.LogKey and pass in here return(new Bk2Controller("", definition ?? MovieController.Definition)); }
private void ActivateMannequinContext(string contextName, Character character, ControllerDefinition controllerDefinition, AnimationDatabase animationDatabase) { var entity = Entity; var scopeContextId = controllerDefinition.FindScopeContext(contextName); //If the id < 0 it means it's invalid. if (scopeContextId < 0) { Log.Error <CharacterAnimator>("Failed to find {0} scope context id in controller definition for Entity {1}.", contextName, Entity.Name); return; } // Setting Scope contexts can happen at any time, and what entity or character instance we have bound to a particular scope context // can change during the lifetime of an action controller. _actionController.SetScopeContext((uint)scopeContextId, entity, character, animationDatabase); }
public GPGXControlConverter(LibGPGX.InputData input) { Console.WriteLine("Genesis Controller report:"); foreach (var e in input.system) { Console.WriteLine("S:{0}", e); } foreach (var e in input.dev) { Console.WriteLine("D:{0}", e); } int player = 1; ControllerDef = new ControllerDefinition(); ControllerDef.BoolButtons.Add("Power"); ControllerDef.BoolButtons.Add("Reset"); for (int i = 0; i < LibGPGX.MAX_DEVICES; i++) { switch (input.dev[i]) { case LibGPGX.INPUT_DEVICE.DEVICE_PAD3B: AddToController(i, player, Genesis3); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_PAD6B: AddToController(i, player, Genesis6); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_MOUSE: AddToController(i, player, Mouse); DoMouseAnalog(i, player); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_NONE: break; case LibGPGX.INPUT_DEVICE.DEVICE_LIGHTGUN: // supports menacers and justifiers AddToController(i, player, Lightgun); DoLightgunAnalog(i, player); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_PAD2B: case LibGPGX.INPUT_DEVICE.DEVICE_PADDLE: case LibGPGX.INPUT_DEVICE.DEVICE_SPORTSPAD: case LibGPGX.INPUT_DEVICE.DEVICE_TEREBI: throw new Exception("Master System only device? Something went wrong."); case LibGPGX.INPUT_DEVICE.DEVICE_ACTIVATOR: AddToController(i, player, Activator); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_XE_A1P: AddToController(i, player, XEA1P); DoXEA1PAnalog(i, player); player++; break; case LibGPGX.INPUT_DEVICE.DEVICE_PICO: // PICO isn't finished on the unmanaged side either throw new Exception("Sega PICO not implemented yet!"); default: throw new Exception("Unknown Genesis control device! Something went wrong."); } } ControllerDef.Name = "GPGX Genesis Controller"; }
static Sameboy() { _gbDefinition = CreateControllerDefinition(1); _sgbDefinition = CreateControllerDefinition(4); }
public O2HawkControllerDeck(string controller1Name, string controller2Name, bool is_G7400) { if (!ValidControllerTypes.ContainsKey(controller1Name)) { throw new InvalidOperationException("Invalid controller type: " + controller1Name); } if (!ValidControllerTypes.ContainsKey(controller2Name)) { throw new InvalidOperationException("Invalid controller type: " + controller2Name); } Port1 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller1Name], 1); Port2 = (IPort)Activator.CreateInstance(ValidControllerTypes[controller2Name], 2); if (is_G7400) { Definition = new ControllerDefinition { Name = Port1.Definition.Name, BoolButtons = Port1.Definition.BoolButtons .Concat(Port2.Definition.BoolButtons) .Concat(new[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "SPC", "?", "L", "P", "+", "W", "E", "R", "T", "U", "I", "O", "Q", "S", "D", "F", "G", "H", "J", "K", "A", "Z", "X", "C", "V", "B", "M", "PERIOD", "-", "*", "/", "=", "YES", "NO", "CLR", "ENT", "Reset", "Power", "SHIFT", "LOCK", "CTNL", ":", "|", "]", "..", ",", "<", "ESC", "BREAK", "RET" }) .ToList() }; } else { Definition = new ControllerDefinition { Name = Port1.Definition.Name, BoolButtons = Port1.Definition.BoolButtons .Concat(Port2.Definition.BoolButtons) .Concat(new[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "SPC", "?", "L", "P", "+", "W", "E", "R", "T", "U", "I", "O", "Q", "S", "D", "F", "G", "H", "J", "K", "A", "Z", "X", "C", "V", "B", "M", "PERIOD", "-", "*", "/", "=", "YES", "NO", "CLR", "ENT", "Reset", "Power" }) .ToList() }; } foreach (var kvp in Port1.Definition.Axes) { Definition.Axes.Add(kvp); } }