Files
ParsonsMasterSystem2026/Core/SmsMachine.cs

102 lines
3.2 KiB
C#

using Core.Cpu;
using Core.Io;
using Core.Memory;
using Core.Video;
using Core.Audio;
using System;
using System.IO;
using System.Collections.Generic;
namespace Core
{
public class SmsMachine
{
public Z80 Cpu { get; private set; }
public SmsMemoryBus MemoryBus { get; private set; }
public SmsIoBus IoBus { get; private set; }
public SmsVdp VideoProcessor { get; private set; }
public SmsApu AudioProcessor { get; private set; }
public ushort? Breakpoint { get; set; } = null;
// NTSC SMS T-States per frame
public const int TStatesPerFrame = 59736; //NTSC
//public const int TStatesPerFrame = 49780; //PAL
public SmsMachine()
{
MemoryBus = new SmsMemoryBus();
VideoProcessor = new SmsVdp();
AudioProcessor = new SmsApu();
IoBus = new SmsIoBus { VideoProcessor = this.VideoProcessor, AudioProcessor = this.AudioProcessor };
Cpu = new Z80(MemoryBus, IoBus);
}
public void LoadCartridge(byte[] romData)
{
MemoryBus.LoadCartridge(romData);
Reset();
}
public void Reset()
{
MemoryBus.CleanRAMData();
Cpu.Reset();
}
public void RunFrame()
{
int tStatesThisFrame = 0;
while (tStatesThisFrame < TStatesPerFrame) // Standard NTSC frame time
{
// 1. Run one CPU instruction
int cycles = Cpu.Step();
tStatesThisFrame += cycles;
// 2. Tell the VDP to catch up
VideoProcessor.Update(cycles);
AudioProcessor.Update(cycles);
// 3. Check if the VDP is begging for attention!
if (VideoProcessor.InterruptPending && Cpu.IFF1)
{
int intCycles = Cpu.RequestInterrupt();
tStatesThisFrame += intCycles;
VideoProcessor.Update(intCycles);
AudioProcessor.Update(intCycles);
}
// 4. THE RESTORED BREAKPOINT TRAP
if (Breakpoint.HasValue && Cpu.PC == Breakpoint.Value)
{
break; // Instantly abort the frame so the debugger can take over!
}
}
}
public void SaveState(string filePath)
{
using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
using (var bw = new System.IO.BinaryWriter(fs))
{
Cpu.SaveState(bw);
MemoryBus.SaveState(bw);
VideoProcessor.SaveState(bw);
AudioProcessor.SaveState(bw);
}
}
public void LoadState(string filePath)
{
if (!System.IO.File.Exists(filePath)) return;
using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
using (var br = new System.IO.BinaryReader(fs))
{
Cpu.LoadState(br);
MemoryBus.LoadState(br);
VideoProcessor.LoadState(br);
AudioProcessor.LoadState(br);
}
}
}
}