Esempio n. 1
0
        public void Map(ushort basea, ushort size, Cart cart)
        {
            if (cart == null)
                throw new ArgumentNullException("cart");

            cart.Attach(M);
            var device = (IDevice)cart;
            if (cart.RequestSnooping)
            {
                Snooper = device;
            }
            Map(basea, size, device);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates an instance of the specified machine.
        /// </summary>
        /// <param name="machineType"></param>
        /// <param name="cart"></param>
        /// <param name="bios">7800 BIOS, optional.</param>
        /// <param name="hsc">7800 High Score cart, optional.</param>
        /// <param name="p1">Left controller, optional.</param>
        /// <param name="p2">Right controller, optional.</param>
        /// <param name="logger"></param>
        /// <exception cref="ArgumentNullException">Cart must not be null.</exception>
        /// <exception cref="Emu7800Exception">Specified MachineType is unexpected.</exception>
        public static MachineBase Create(MachineType machineType, Cart cart, Bios7800 bios, HSC7800 hsc, Controller p1, Controller p2, ILogger logger)
        {
            if (cart == null)
                throw new ArgumentNullException("cart");

            MachineBase m;
            switch (machineType)
            {
                case MachineType.A2600NTSC:
                    m = new Machine2600NTSC(cart, logger);
                    break;
                case MachineType.A2600PAL:
                    m = new Machine2600PAL(cart, logger);
                    break;
                case MachineType.A7800NTSC:
                    m = new Machine7800NTSC(cart, bios, hsc, logger);
                    break;
                case MachineType.A7800PAL:
                    m = new Machine7800PAL(cart, bios, hsc, logger);
                    break;
                default:
                    throw new Emu7800Exception("Unexpected MachineType: " + machineType);
            }

            m.InputState.LeftControllerJack = p1;
            m.InputState.RightControllerJack = p2;

            m.Reset();

            return m;
        }
Esempio n. 3
0
 public void Write(Cart cart)
 {
     WriteTypeName(cart);
     cart.GetObjectData(this);
 }
Esempio n. 4
0
        void HardReset()
        {
            cart = Cart.Create(rom, GameInfo.CartType);
            ILogger logger = new ConsoleLogger();

            HSC7800 hsc7800 = null;
            if (hsbios != null)
            {
                hsc7800 = new HSC7800(hsbios, hsram);
            }

            Bios7800 bios7800 = new Bios7800(bios);
            theMachine = MachineBase.Create
                (GameInfo.MachineType,
                cart,
                bios7800,
                hsc7800,
                GameInfo.LController,
                GameInfo.RController,
                logger);

            theMachine.Reset();
            theMachine.InputState.InputPollCallback = InputCallbacks.Call;

            ControlAdapter = new Atari7800Control(theMachine);
            ControllerDefinition = ControlAdapter.ControlType;

            avProvider.ConnectToMachine(theMachine, GameInfo);
            // to sync exactly with audio as this emulator creates and times it, the frame rate should be exactly 60:1 or 50:1
            CoreComm.VsyncNum = theMachine.FrameHZ;
            CoreComm.VsyncDen = 1;

            SetupMemoryDomains(hsc7800);
        }
        public override void ComputeNextFrame(FrameBuffer frameBuffer)
        {
            base.ComputeNextFrame(frameBuffer);

            AssertDebug(CPU.Jammed || CPU.RunClocks <= 0 && (CPU.RunClocks % CPU.RunClocksMultiple) == 0);
            AssertDebug(CPU.Jammed || ((CPU.Clock + (ulong)(CPU.RunClocks / CPU.RunClocksMultiple)) % (114 * (ulong)FrameBuffer.Scanlines)) == 0);

            ulong startOfScanlineCpuClock = 0;

            Maria.StartFrame();
            Cart.StartFrame();
            for (var i = 0; i < FrameBuffer.Scanlines && !CPU.Jammed; i++)
            {
                AssertDebug(CPU.RunClocks <= 0 && (CPU.RunClocks % CPU.RunClocksMultiple) == 0);
                var newStartOfScanlineCpuClock = CPU.Clock + (ulong)(CPU.RunClocks / CPU.RunClocksMultiple);

                AssertDebug(startOfScanlineCpuClock == 0 || newStartOfScanlineCpuClock == startOfScanlineCpuClock + 114);
                startOfScanlineCpuClock = newStartOfScanlineCpuClock;

                CPU.RunClocks += (7 * CPU.RunClocksMultiple);
                var remainingRunClocks = (114 - 7) * CPU.RunClocksMultiple;

                CPU.Execute();
                if (CPU.Jammed)
                {
                    break;
                }
                if (CPU.EmulatorPreemptRequest)
                {
                    Maria.DoDMAProcessing();
                    var remainingCpuClocks = 114 - (CPU.Clock - startOfScanlineCpuClock);
                    CPU.Clock    += remainingCpuClocks;
                    CPU.RunClocks = 0;
                    continue;
                }

                var dmaClocks = Maria.DoDMAProcessing();

                // CHEAT: Ace of Aces: Title screen has a single scanline flicker without this. Maria DMA clock counting probably not 100% accurate.
                if (i == 203 && FrameBuffer.Scanlines == 262 /*NTSC*/ || i == 228 && FrameBuffer.Scanlines == 312 /*PAL*/)
                {
                    if (dmaClocks == 152 && remainingRunClocks == 428 && (CPU.RunClocks == -4 || CPU.RunClocks == -8))
                    {
                        dmaClocks -= 4;
                    }
                }

                // Unsure exactly what to do if Maria DMA processing extends past the current scanline.
                // For now, throw away half remaining until we are within the current scanline.
                // KLAX initialization starts DMA without initializing the DLL data structure.
                // Maria processing then runs away causing an invalid CPU opcode to be executed that jams the machine.
                // So Maria must give up at some point, but not clear exactly how.
                // Anyway, this makes KLAX work without causing breakage elsewhere.
                while ((CPU.RunClocks + remainingRunClocks) < dmaClocks)
                {
                    dmaClocks >>= 1;
                }

                // Assume the CPU waits until the next div4 boundary to proceed after DMA processing.
                if ((dmaClocks & 3) != 0)
                {
                    dmaClocks += 4;
                    dmaClocks -= (dmaClocks & 3);
                }

                CPU.Clock     += (ulong)(dmaClocks / CPU.RunClocksMultiple);
                CPU.RunClocks -= dmaClocks;

                CPU.RunClocks += remainingRunClocks;

                CPU.Execute();
                if (CPU.Jammed)
                {
                    break;
                }
                if (CPU.EmulatorPreemptRequest)
                {
                    var remainingCpuClocks = 114 - (CPU.Clock - startOfScanlineCpuClock);
                    CPU.Clock    += remainingCpuClocks;
                    CPU.RunClocks = 0;
                }
            }
            Cart.EndFrame();
            Maria.EndFrame();
        }