Example #1
0
        /*
         * FrameAdvance() and MAME
         *
         * MAME fires the periodic callback on every video and debugger update,
         * which happens every VBlank and also repeatedly at certain time
         * intervals while paused. Since MAME's luaengine runs in a separate
         * thread, it's only safe to update everything we need per frame during
         * this callback, when it's explicitly waiting for further lua commands.
         *
         * If we disable throttling and pass -update_in_pause, there will be no
         * delay between video updates. This allows to run at full speed while
         * frame-stepping.
         *
         * MAME only captures new frame data once per VBlank, while unpaused.
         * But it doesn't have an exclusive VBlank callback we could attach to.
         * It has a LUA_ON_FRAME_DONE callback, but that fires even more
         * frequently and updates all sorts of other non-video stuff, and we
         * need none of that here.
         *
         * So we filter out all the calls that happen while paused (non-VBlank
         * updates). Then, when Hawk asks us to advance a frame, we virtually
         * unpause and declare the new frame unfinished. This informs MAME that
         * it should advance one frame internally. Hawk starts waiting for the
         * MAME thread to complete the request.
         *
         * After MAME's done advancing, it fires the periodic callback again.
         * That's when we update everything and declare the new frame finished,
         * filtering out any further updates again. Then we allow Hawk to
         * complete frame-advancing.
         */
        private void MAMEPeriodicCallback()
        {
            if (_exiting)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Exit);
                _exiting = false;
            }

            if (_memAccess)
            {
                _mamePeriodicComplete.Set();
                _memoryAccessComplete.WaitOne();
                return;
            }

            //int MAMEFrame = LibMAME.mame_lua_get_int(MAMELuaCommand.GetFrameNumber);

            if (!_paused)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Step);
                _frameDone = false;
                _paused    = true;
            }
            else if (!_frameDone)
            {
                Update();
                _frameDone = true;
                _mameFrameComplete.Set();
            }
        }
Example #2
0
 private void MAMEBootCallback()
 {
     LibMAME.mame_lua_execute(MAMELuaCommand.Pause);
     CheckVersions();
     GetInputFields();
     Update();
     MAMEStartupComplete.Set();
 }
 private void SendInput()
 {
     foreach (var fieldPort in _fieldsPorts)
     {
         LibMAME.mame_lua_execute(
             "manager:machine():ioport()" +
             $".ports  [\"{ fieldPort.Value }\"]" +
             $".fields [\"{ fieldPort.Key   }\"]" +
             $":set_value({ (_controller.IsPressed(fieldPort.Key) ? 1 : 0) })");
     }
 }
Example #4
0
        public void OverrideGameSettings()
        {
            foreach (KeyValuePair <string, string> setting in _syncSettings.DriverSettings)
            {
                DriverSetting s = CurrentDriverSettings.SingleOrDefault(s => s.LookupKey == setting.Key);

                if (s != null && s.Type == SettingType.DIPSWITCH)
                {
                    LibMAME.mame_lua_execute($"{ s.LuaCode }.user_value = { setting.Value }");
                }
            }
        }
Example #5
0
        private void MAMEBootCallback()
        {
            LibMAME.mame_lua_execute(MAMELuaCommand.Pause);

            CheckVersions();
            GetInputFields();
            Update();
            UpdateGameName();
            InitMemoryDomains();

            _mameStartupComplete.Set();
        }
Example #6
0
        public void LoadStateBinary(BinaryReader reader)
        {
            int length = reader.ReadInt32();

            if (length != _mameSaveBuffer.Length)
            {
                throw new InvalidOperationException("Savestate buffer size mismatch!");
            }

            reader.Read(_mameSaveBuffer, 0, _mameSaveBuffer.Length);
            Frame = reader.ReadInt32();

            LibMAME.mame_lua_execute($"manager:machine():buffer_load({ _mameSaveBuffer })");
        }
Example #7
0
        /*
         * FrameAdvance() and MAME
         *
         * MAME fires the periodic callback on every video and debugger update,
         * which happens every VBlank and also repeatedly at certain time
         * intervals while paused. Since MAME's luaengine runs in a separate
         * thread, it's only safe to update everything we need per frame during
         * this callback, when it's explicitly waiting for further lua commands.
         *
         * If we disable throttling and pass -update_in_pause, there will be no
         * delay between video updates. This allows to run at full speed while
         * frame-stepping.
         *
         * MAME only captures new frame data once per VBlank, while unpaused.
         * But it doesn't have an exclusive VBlank callback we could attach to.
         * It has a LUA_ON_FRAME_DONE callback, but that fires even more
         * frequently and updates all sorts of other non-video stuff, and we
         * need none of that here.
         *
         * So we filter out all the calls that happen while paused (non-VBlank
         * updates). Then, when Hawk asks us to advance a frame, we virtually
         * unpause and declare the new frame unfinished. This informs MAME that
         * it should advance one frame internally. Hawk starts waiting for the
         * MAME thread to complete the request.
         *
         * After MAME's done advancing, it fires the periodic callback again.
         * That's when we update everything and declare the new frame finished,
         * filtering out any further updates again. Then we allow Hawk to
         * complete frame-advancing.
         */
        private void MAMEPeriodicCallback()
        {
            if (_exiting)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Exit);
                _exiting = false;
            }

            if (_memAccess)
            {
                _mamePeriodicComplete.Set();
                _memoryAccessComplete.WaitOne();
                return;
            }

            //int MAMEFrame = LibMAME.mame_lua_get_int(MAMELuaCommand.GetFrameNumber);

            if (!_paused)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Step);
                _frameDone = false;
                _paused    = true;
            }
            else if (!_frameDone)
            {
                /*
                 * IntPtr ptr = LibMAME.mame_lua_get_string(MAMELuaCommand.GetSpaceBuffer, out var lengthInBytes);
                 *
                 * if (ptr == IntPtr.Zero)
                 * {
                 *      Console.WriteLine("LibMAME ERROR: audio buffer pointer is null");
                 *      return;
                 * }
                 *
                 * //byte[] buf = new byte[lengthInBytes];
                 * //Marshal.Copy(ptr, buf, 0, lengthInBytes);
                 *
                 * if (!LibMAME.mame_lua_free_string(ptr))
                 * {
                 *      Console.WriteLine("LibMAME ERROR: audio buffer wasn't freed");
                 * }
                 */

                Update();
                _frameDone = true;
                _mameFrameComplete.Set();
            }
        }
Example #8
0
        private void MAMEBootCallback()
        {
            LibMAME.mame_lua_execute(MAMELuaCommand.Pause);

            CheckVersions();
            GetInputFields();
            Update();
            UpdateGameName();
            InitMemoryDomains();

            IntPtr ptr = LibMAME.mame_lua_get_string("return manager:machine():buffer_save()", out var lengthInBytes);

            _mameSaveBuffer = new byte[lengthInBytes];
            _hawkSaveBuffer = new byte[lengthInBytes + 4 + 4];

            _mameStartupComplete.Set();
        }
        private void _poke(long addr, byte val, int firstOffset, long size)
        {
            if (addr < 0 || addr >= size)
            {
                throw new ArgumentOutOfRangeException();
            }

            if (!_memAccess)
            {
                _memAccess = true;
                _mamePeriodicComplete.WaitOne();
            }

            addr += firstOffset;

            LibMAME.mame_lua_execute($"{ MAMELuaCommand.GetSpace }:write_u8({ addr << _systemBusAddressShift }, { val })");

            _memoryAccessComplete.Set();
        }
Example #10
0
        private void MAMEBootCallback()
        {
            LibMAME.mame_lua_execute(MAMELuaCommand.Pause);

            CheckVersions();
            GetInputFields();
            UpdateVideo();
            UpdateAspect();
            UpdateFramerate();
            UpdateGameName();
            InitMemoryDomains();

            int length = LibMAME.mame_lua_get_int("return string.len(manager:machine():buffer_save())");

            _mameSaveBuffer = new byte[length];
            _hawkSaveBuffer = new byte[length + 4 + 4 + 4 + 1];

            _mameStartupComplete.Set();
        }
Example #11
0
        /*
         * FrameAdvance() and MAME
         *
         * MAME fires the periodic callback on every video and debugger update,
         * which happens every VBlank and also repeatedly at certain time
         * intervals while paused. Since MAME's luaengine runs in a separate
         * thread, it's only safe to update everything we need per frame during
         * this callback, when it's explicitly waiting for further lua commands.
         *
         * If we disable throttling and pass -update_in_pause, there will be no
         * delay between video updates. This allows to run at full speed while
         * frame-stepping.
         *
         * MAME only captures new frame data once per VBlank, while unpaused.
         * But it doesn't have an exclusive VBlank callback we could attach to.
         * It has a LUA_ON_FRAME_DONE callback, but that fires even more
         * frequently and updates all sorts of other non-video stuff, and we
         * need none of that here.
         *
         * So we filter out all the calls that happen while paused (non-VBlank
         * updates). Then, when Hawk asks us to advance a frame, we virtually
         * unpause and declare the new frame unfinished. This informs MAME that
         * it should advance one frame internally. Hawk starts waiting for the
         * MAME thread to complete the request.
         *
         * After MAME's done advancing, it fires the periodic callback again.
         * That's when we update everything and declare the new frame finished,
         * filtering out any further updates again. Then we allow Hawk to
         * complete frame-advancing.
         */
        private void MAMEPeriodicCallback()
        {
            if (exiting)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Exit);
                exiting = false;
            }

            int MAMEFrame = LibMAME.mame_lua_get_int(MAMELuaCommand.GetFrameNumber);

            if (!paused)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Step);
                frameDone = false;
                paused    = true;
            }
            else if (!frameDone)
            {
                Update();
                frameDone = true;
                MAMEFrameComplete.Set();
            }
        }
Example #12
0
        private void MAMEPeriodicCallback()
        {
            if (_exiting)
            {
                LibMAME.mame_lua_execute(MAMELuaCommand.Exit);
                _exiting = false;
            }

            for (; _memAccess;)
            {
                _mamePeriodicComplete.Set();
                _memoryAccessComplete.WaitOne();

                if (!_frameDone && !_paused || _exiting)                 // FrameAdvance() has been requested
                {
                    _memAccess = false;
                    return;
                }
            }

            //int MAMEFrame = LibMAME.mame_lua_get_int(MAMELuaCommand.GetFrameNumber);

            if (!_paused)
            {
                SendInput();
                LibMAME.mame_lua_execute(MAMELuaCommand.Step);
                _frameDone = false;
                _paused    = true;
            }
            else if (!_frameDone)
            {
                UpdateVideo();
                _frameDone = true;
                _mameFrameComplete.Set();
            }
        }
Example #13
0
        private void InitMemoryDomains()
        {
            var domains = new List <MemoryDomain>();

            _systemBusAddressShift = LibMAME.mame_lua_get_int(MAMELuaCommand.GetSpaceAddressShift);
            var size         = (long)LibMAME.mame_lua_get_double(MAMELuaCommand.GetSpaceAddressMask) + 1;
            var dataWidth    = LibMAME.mame_lua_get_int(MAMELuaCommand.GetSpaceDataWidth) >> 3;          // mame returns in bits
            var endianString = MameGetString(MAMELuaCommand.GetSpaceEndianness);

            MemoryDomain.Endian endian = MemoryDomain.Endian.Unknown;

            if (endianString == "little")
            {
                endian = MemoryDomain.Endian.Little;
            }
            else if (endianString == "big")
            {
                endian = MemoryDomain.Endian.Big;
            }

            var mapCount = LibMAME.mame_lua_get_int(MAMELuaCommand.GetSpaceMapCount);

            for (int i = 1; i <= mapCount; i++)
            {
                var read  = MameGetString($"return { MAMELuaCommand.SpaceMap }[{ i }].readtype");
                var write = MameGetString($"return { MAMELuaCommand.SpaceMap }[{ i }].writetype");

                if (read == "ram" && write == "ram" /* || read == "rom" */)
                {
                    var firstOffset = LibMAME.mame_lua_get_int($"return { MAMELuaCommand.SpaceMap }[{ i }].offset");
                    var lastOffset  = LibMAME.mame_lua_get_int($"return { MAMELuaCommand.SpaceMap }[{ i }].endoff");
                    var name        = $"{ read.ToUpper() } { firstOffset:X}-{ lastOffset:X}";

                    domains.Add(new MemoryDomainDelegate(name, lastOffset - firstOffset + 1, endian,
                                                         delegate(long addr)
                    {
                        if (addr < 0 || addr >= size)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        _memAccess = true;
                        _mamePeriodicComplete.WaitOne();
                        addr   += firstOffset;
                        var val = (byte)LibMAME.mame_lua_get_int($"{ MAMELuaCommand.GetSpace }:read_u8({ addr << _systemBusAddressShift })");
                        _memoryAccessComplete.Set();
                        _memAccess = false;
                        return(val);
                    },
                                                         read == "rom" ? (Action <long, byte>) null : delegate(long addr, byte val)
                    {
                        if (addr < 0 || addr >= size)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        _memAccess = true;
                        _mamePeriodicComplete.WaitOne();
                        addr += firstOffset;
                        LibMAME.mame_lua_execute($"{ MAMELuaCommand.GetSpace }:write_u8({ addr << _systemBusAddressShift }, { val })");
                        _memoryAccessComplete.Set();
                        _memAccess = false;
                    }, dataWidth));
                }
            }

            domains.Add(new MemoryDomainDelegate("System Bus", size, endian,
                                                 delegate(long addr)
            {
                if (addr < 0 || addr >= size)
                {
                    throw new ArgumentOutOfRangeException();
                }

                _memAccess = true;
                _mamePeriodicComplete.WaitOne();
                var val = (byte)LibMAME.mame_lua_get_int($"{ MAMELuaCommand.GetSpace }:read_u8({ addr << _systemBusAddressShift })");
                _memoryAccessComplete.Set();
                _memAccess = false;
                return(val);
            },
                                                 null, dataWidth));

            _memoryDomains = new MemoryDomainList(domains);
            (ServiceProvider as BasicServiceProvider).Register <IMemoryDomains>(_memoryDomains);
        }