Fixed per scanline interrupts. No artifacts in MMCOI
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<StartupObject>Desktop.Program</StartupObject>
|
||||
<AssemblyName>Parsons Master System</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
36
Desktop/Form1.Designer.cs
generated
36
Desktop/Form1.Designer.cs
generated
@@ -36,11 +36,13 @@
|
||||
exitToolStripMenuItem = new ToolStripMenuItem();
|
||||
viewToolStripMenuItem = new ToolStripMenuItem();
|
||||
debuggerToolStripMenuItem = new ToolStripMenuItem();
|
||||
vRAMViewerToolStripMenuItem = new ToolStripMenuItem();
|
||||
machineToolStripMenuItem = new ToolStripMenuItem();
|
||||
resetToolStripMenuItem = new ToolStripMenuItem();
|
||||
helpToolStripMenuItem = new ToolStripMenuItem();
|
||||
aboutToolStripMenuItem = new ToolStripMenuItem();
|
||||
vRAMViewerToolStripMenuItem = new ToolStripMenuItem();
|
||||
saveStateToolStripMenuItem = new ToolStripMenuItem();
|
||||
loadStateToolStripMenuItem = new ToolStripMenuItem();
|
||||
menuStrip1.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
@@ -99,13 +101,20 @@
|
||||
// debuggerToolStripMenuItem
|
||||
//
|
||||
debuggerToolStripMenuItem.Name = "debuggerToolStripMenuItem";
|
||||
debuggerToolStripMenuItem.Size = new Size(270, 34);
|
||||
debuggerToolStripMenuItem.Size = new Size(221, 34);
|
||||
debuggerToolStripMenuItem.Text = "Debugger";
|
||||
debuggerToolStripMenuItem.Click += debuggerToolStripMenuItem_Click;
|
||||
//
|
||||
// vRAMViewerToolStripMenuItem
|
||||
//
|
||||
vRAMViewerToolStripMenuItem.Name = "vRAMViewerToolStripMenuItem";
|
||||
vRAMViewerToolStripMenuItem.Size = new Size(221, 34);
|
||||
vRAMViewerToolStripMenuItem.Text = "VRAM Viewer";
|
||||
vRAMViewerToolStripMenuItem.Click += vramViewerToolStripMenuItem_Click;
|
||||
//
|
||||
// machineToolStripMenuItem
|
||||
//
|
||||
machineToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { resetToolStripMenuItem });
|
||||
machineToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { resetToolStripMenuItem, saveStateToolStripMenuItem, loadStateToolStripMenuItem });
|
||||
machineToolStripMenuItem.Name = "machineToolStripMenuItem";
|
||||
machineToolStripMenuItem.Size = new Size(94, 29);
|
||||
machineToolStripMenuItem.Text = "Machine";
|
||||
@@ -113,7 +122,7 @@
|
||||
// resetToolStripMenuItem
|
||||
//
|
||||
resetToolStripMenuItem.Name = "resetToolStripMenuItem";
|
||||
resetToolStripMenuItem.Size = new Size(156, 34);
|
||||
resetToolStripMenuItem.Size = new Size(270, 34);
|
||||
resetToolStripMenuItem.Text = "Reset";
|
||||
resetToolStripMenuItem.Click += resetToolStripMenuItem_Click;
|
||||
//
|
||||
@@ -130,12 +139,19 @@
|
||||
aboutToolStripMenuItem.Size = new Size(164, 34);
|
||||
aboutToolStripMenuItem.Text = "About";
|
||||
//
|
||||
// vRAMViewerToolStripMenuItem
|
||||
// saveStateToolStripMenuItem
|
||||
//
|
||||
vRAMViewerToolStripMenuItem.Name = "vRAMViewerToolStripMenuItem";
|
||||
vRAMViewerToolStripMenuItem.Size = new Size(270, 34);
|
||||
vRAMViewerToolStripMenuItem.Text = "VRAM Viewer";
|
||||
vRAMViewerToolStripMenuItem.Click += vramViewerToolStripMenuItem_Click;
|
||||
saveStateToolStripMenuItem.Name = "saveStateToolStripMenuItem";
|
||||
saveStateToolStripMenuItem.Size = new Size(270, 34);
|
||||
saveStateToolStripMenuItem.Text = "Save State";
|
||||
saveStateToolStripMenuItem.Click += saveStateToolStripMenuItem_Click;
|
||||
//
|
||||
// loadStateToolStripMenuItem
|
||||
//
|
||||
loadStateToolStripMenuItem.Name = "loadStateToolStripMenuItem";
|
||||
loadStateToolStripMenuItem.Size = new Size(270, 34);
|
||||
loadStateToolStripMenuItem.Text = "Load State";
|
||||
loadStateToolStripMenuItem.Click += loadStateToolStripMenuItem_Click;
|
||||
//
|
||||
// ParsonsForm1
|
||||
//
|
||||
@@ -168,5 +184,7 @@
|
||||
private ToolStripMenuItem includedToolStripMenuItem;
|
||||
private ToolStripMenuItem selectROMToolStripMenuItem1;
|
||||
private ToolStripMenuItem vRAMViewerToolStripMenuItem;
|
||||
private ToolStripMenuItem saveStateToolStripMenuItem;
|
||||
private ToolStripMenuItem loadStateToolStripMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
109
Desktop/Form1.cs
109
Desktop/Form1.cs
@@ -37,13 +37,8 @@ namespace Desktop
|
||||
public ParsonsForm1()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.Text = $"Parsons Master System 2026 - {_currentRomName}";
|
||||
_machine = new SmsMachine();
|
||||
_audioPlayer = new NAudioPlayer();
|
||||
_machine.AudioProcessor.AudioDevice = _audioPlayer;
|
||||
|
||||
PopulateIncludedRomsMenu();
|
||||
|
||||
// These are perfectly safe for the Visual Studio Designer!
|
||||
this.KeyPreview = true;
|
||||
this.KeyDown += Form1_KeyDown;
|
||||
this.KeyUp += Form1_KeyUp;
|
||||
@@ -51,6 +46,21 @@ namespace Desktop
|
||||
this.ResizeRedraw = true;
|
||||
}
|
||||
|
||||
// The Designer ignores this completely, but the compiled game runs it instantly!
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
base.OnLoad(e);
|
||||
|
||||
this.Text = $"Parsons Master System - {_currentRomName}";
|
||||
|
||||
// Safe to initialize hardware and files here!
|
||||
_machine = new SmsMachine();
|
||||
_audioPlayer = new NAudioPlayer();
|
||||
_machine.AudioProcessor.AudioDevice = _audioPlayer;
|
||||
|
||||
PopulateIncludedRomsMenu();
|
||||
}
|
||||
|
||||
private void DrawScreen()
|
||||
{
|
||||
// Rapidly copy our VDP FrameBuffer into the Windows Bitmap
|
||||
@@ -65,7 +75,8 @@ namespace Desktop
|
||||
// Always call the base method so Windows can draw your MenuStrip!
|
||||
base.OnPaint(e);
|
||||
|
||||
if (_screenBitmap != null)
|
||||
// THE FIX: We MUST ensure the designer has actually built the menu strip before asking for its height!
|
||||
if (_screenBitmap != null && menuStrip1 != null)
|
||||
{
|
||||
// 1. Set the rendering mode for perfect, chunky retro pixels!
|
||||
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
||||
@@ -73,7 +84,7 @@ namespace Desktop
|
||||
|
||||
// 2. Calculate the drawing area.
|
||||
// We start drawing BELOW the MenuStrip so it doesn't get covered up.
|
||||
int topOffset = menuStrip1.Height; // Change 'menuStrip1' if your menu has a different (Name)
|
||||
int topOffset = menuStrip1.Height;
|
||||
Rectangle renderArea = new Rectangle(
|
||||
0,
|
||||
topOffset,
|
||||
@@ -205,42 +216,37 @@ namespace Desktop
|
||||
_currentRomName = Path.GetFileNameWithoutExtension(filePath);
|
||||
this.Text = $"Parsons Master System - {_currentRomName}";
|
||||
|
||||
// 5. LOAD THE NEW SAVE DATA!
|
||||
string savPath = Path.ChangeExtension(_currentRomPath, ".sav");
|
||||
_machine.MemoryBus.LoadSaveData(savPath);
|
||||
// 5. LOAD THE NEW SAVE DATA FROM THE EXE FOLDER!
|
||||
string savPath = GetSaveFilePath();
|
||||
if (savPath != null)
|
||||
{
|
||||
_machine.MemoryBus.LoadSaveData(savPath);
|
||||
}
|
||||
|
||||
// 6. Turn the power on!
|
||||
StartEmulator();
|
||||
}
|
||||
private string GetSaveFilePath()
|
||||
{
|
||||
// Don't try to save if a game hasn't been loaded yet!
|
||||
if (string.IsNullOrEmpty(_currentRomName) || _currentRomName == "No ROM")
|
||||
return null;
|
||||
|
||||
//private async void LoadRomAndStart(string filePath)
|
||||
//{
|
||||
// StopEmulator();
|
||||
// if (_emulatorTask != null)
|
||||
// {
|
||||
// await _emulatorTask;
|
||||
// }
|
||||
// Application.StartupPath is the exact folder containing your .exe
|
||||
string exeFolder = Application.StartupPath;
|
||||
|
||||
// // 2. Load the file
|
||||
// byte[] rom = File.ReadAllBytes(filePath);
|
||||
|
||||
// // 3. Jam it into the Sega Mapper
|
||||
// _machine.LoadCartridge(rom);
|
||||
|
||||
// _currentRomName = Path.GetFileNameWithoutExtension(filePath);
|
||||
// this.Text = $"Parsons Master System - {_currentRomName}";
|
||||
|
||||
// // 5. Turn the power on!
|
||||
|
||||
// StartEmulator();
|
||||
//}
|
||||
// Combines the exe folder with "GameName.sav"
|
||||
return Path.Combine(exeFolder, _currentRomName + ".sav");
|
||||
}
|
||||
private void SaveCurrentSram()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_currentRomPath) && _machine != null)
|
||||
if (_machine != null)
|
||||
{
|
||||
// Swaps ".sms" for ".sav"
|
||||
string savPath = Path.ChangeExtension(_currentRomPath, ".sav");
|
||||
_machine.MemoryBus.SaveSaveData(savPath);
|
||||
string savPath = GetSaveFilePath();
|
||||
if (savPath != null)
|
||||
{
|
||||
_machine.MemoryBus.SaveSaveData(savPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,5 +367,38 @@ namespace Desktop
|
||||
SaveCurrentSram();
|
||||
_audioPlayer?.Stop();
|
||||
}
|
||||
private async void saveStateToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentRomName) || _currentRomName == "No ROM") return;
|
||||
|
||||
// 1. Politely ask the emulator loop to pause, and wait for it to finish its current frame!
|
||||
StopEmulator();
|
||||
if (_emulatorTask != null) await _emulatorTask;
|
||||
|
||||
// 2. Change the extension to .state and save it right next to the .exe
|
||||
string statePath = Path.ChangeExtension(GetSaveFilePath(), ".state");
|
||||
_machine.SaveState(statePath);
|
||||
|
||||
// 3. Resume the emulator seamlessly
|
||||
StartEmulator();
|
||||
}
|
||||
|
||||
private async void loadStateToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentRomName) || _currentRomName == "No ROM") return;
|
||||
|
||||
string statePath = Path.ChangeExtension(GetSaveFilePath(), ".state");
|
||||
if (!File.Exists(statePath)) return;
|
||||
|
||||
// 1. Pause the emulator
|
||||
StopEmulator();
|
||||
if (_emulatorTask != null) await _emulatorTask;
|
||||
|
||||
// 2. Inject the frozen state into the silicon!
|
||||
_machine.LoadState(statePath);
|
||||
|
||||
// 3. Resume
|
||||
StartEmulator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user