Пример #1
0
        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();
                }
            }
        }
Пример #2
0
            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();
            }
Пример #3
0
        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;
        }
Пример #4
0
        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
            };
        }
Пример #5
0
 public Bk2ControllerDefinition(ControllerDefinition source)
     : base(source)
 {
 }
Пример #6
0
 /// <summary>don't do this</summary>
 public void ForceType(ControllerDefinition newType) => Definition = newType;
Пример #7
0
 public SnesSaveController(ControllerDefinition def)
 {
     this.def = def;
 }
Пример #8
0
 public ControllerNES()
 {
     ControllerDefFragment = new("(NES Controller fragment)") { BoolButtons = Buttons.OrderBy(x => _buttonOrdinals[x]).ToList() };
 }
Пример #9
0
 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);
        }
Пример #12
0
        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;
                    }
                }
            }
        }
Пример #13
0
 public SimpleController(ControllerDefinition definition)
 => Definition = definition;
Пример #14
0
        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());
        }
Пример #15
0
 static Pizza()
 {
     _gbDefinition  = CreateControllerDefinition(1);
     _sgbDefinition = CreateControllerDefinition(4);
 }
Пример #16
0
 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
Пример #17
0
        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();
                }
            }
        }
Пример #18
0
        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);
        }
Пример #19
0
 public SnesSaveController()
 {
     this.def = null;
 }
Пример #20
0
 public AutofireController(ControllerDefinition definition)
 {
     On    = Global.Config.AutofireOn < 1 ? 0 : Global.Config.AutofireOn;
     Off   = Global.Config.AutofireOff < 1 ? 0 : Global.Config.AutofireOff;
     _type = definition;
 }
Пример #21
0
			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();
			}
Пример #22
0
 /// <summary>don't do this</summary>
 public void ForceType(ControllerDefinition newtype)
 {
     _type = newtype;
 }
Пример #23
0
        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();
                }
            }
        }
Пример #24
0
 public void RecreateMovieController(ControllerDefinition definition)
 {
     MovieController = new Bk2Controller(definition);
 }
Пример #25
0
        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;
                }
            }
        }
Пример #26
0
 public IMovieController GenerateMovieController(ControllerDefinition definition = null)
 {
     // TODO: expose Movie.LogKey and pass in here
     return(new Bk2Controller("", definition ?? MovieController.Definition));
 }
Пример #27
0
        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);
        }
Пример #28
0
        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";
        }
Пример #29
0
 static Sameboy()
 {
     _gbDefinition  = CreateControllerDefinition(1);
     _sgbDefinition = CreateControllerDefinition(4);
 }
Пример #30
0
        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);
            }
        }