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); }
/// <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; }
public void Write(Cart cart) { WriteTypeName(cart); cart.GetObjectData(this); }
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(); }