Some fixes and code refactoring

This commit is contained in:
2026-05-22 16:40:33 +01:00
parent cca1abf0be
commit b5695b5c2f
7 changed files with 233 additions and 190 deletions

View File

@@ -59,6 +59,7 @@ namespace Desktop
_machine = new SmsMachine();
_audioPlayer = new NAudioPlayer();
_machine.AudioProcessor.AudioDevice = _audioPlayer;
IsRunning = false;
PopulateIncludedRomsMenu();
}
@@ -127,7 +128,7 @@ namespace Desktop
e.Graphics.DrawImage(_screenBitmap, destRect, sourceRect, GraphicsUnit.Pixel);
}
}
public void StartEmulator()
{
@@ -253,50 +254,51 @@ namespace Desktop
{
IsRunning = false;
}
private async void LoadRomAndStart(string filePath)
private async void LoadRomDataAndStart(byte[] romData, string fileName, string uniqueId)
{
StopEmulator();
if (_emulatorTask != null)
{
await _emulatorTask;
}
_romType = Path.GetExtension(filePath);
if (_romType == ".sms")
{
_machine.VideoProcessor.IsGameGear = false;
}
else if (_romType == ".gg")
{
_machine.VideoProcessor.IsGameGear = true;
}
else
throw new Exception("Incorrect ROM Type!");
_romType = _machine.VideoProcessor.IsGameGear ? "GG" : "SMS";
// 1. SAVE THE PREVIOUS GAME!
SaveCurrentSram();
// 2. Load the file
byte[] rom = File.ReadAllBytes(filePath);
// Blast the bytes straight into the virtual cartridge slot!
_machine.LoadCartridge(romData);
// 3. Jam it into the Sega Mapper
_machine.LoadCartridge(rom);
// Check the hardware mode based on the file name
bool isGG = fileName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase);
_machine.VideoProcessor.IsGameGear = isGG;
// 4. Update the path tracking
_currentRomPath = filePath;
_currentRomName = Path.GetFileNameWithoutExtension(filePath);
//this.Text = $"{_romType} Parsons Master System 2026 - {_currentRomName}";
// We use uniqueId to track the SRAM file path (works for both real paths and resource names)
_currentRomPath = uniqueId;
_currentRomName = Path.GetFileNameWithoutExtension(fileName);
// Update the window title dynamically
_romType = isGG ? "GG" : "MS";
this.Text = $"{_romType} Parsons Master System 2026 - {_currentRomName}";
// 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 void LoadRomAndStart(string filePath)
{
if (!File.Exists(filePath)) return;
// Read from the hard drive, then pass to the universal loader
byte[] romData = File.ReadAllBytes(filePath);
LoadRomDataAndStart(romData, Path.GetFileName(filePath), filePath);
}
private string GetSaveFilePath()
{
// Don't try to save if a game hasn't been loaded yet!
@@ -339,7 +341,7 @@ namespace Desktop
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(menuName);
// 3. Point the click event to our new extraction helper!
romMenuItem.Click += (sender, e) => ExtractAndLoadEmbeddedRom(resourceName);
romMenuItem.Click += (sender, e) => LoadEmbeddedRom(resourceName);
// 4. Sort into the correct menu based on extension!
if (resourceName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase))
@@ -353,32 +355,28 @@ namespace Desktop
}
}
private void ExtractAndLoadEmbeddedRom(string resourceName)
private void LoadEmbeddedRom(string resourceName)
{
// 1. Strip off the ugly "Desktop.ROMS." prefix to get the real file name
// 1. Strip off the ugly prefix to get the real file name for the UI and the .gg check
string cleanFileName = resourceName.Replace("Desktop.ROMS.", "");
// 2. Create a physical path right next to your emulator .exe
string physicalPath = Path.Combine(Application.StartupPath, cleanFileName);
Assembly assembly = Assembly.GetExecutingAssembly();
// 3. If we haven't extracted this game yet, extract it now!
if (!File.Exists(physicalPath))
// 2. Open a direct pipe to the internal resource
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
Assembly assembly = Assembly.GetExecutingAssembly();
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null) return;
using (FileStream fileStream = new FileStream(physicalPath, FileMode.Create))
{
stream.CopyTo(fileStream);
}
}
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
}
if (stream == null) return;
// 4. Now that it is a REAL file on the hard drive, pass it to your normal loader!
LoadRomAndStart(physicalPath);
// 3. Copy the stream entirely in RAM—never touching the hard drive!
using (MemoryStream ms = new MemoryStream())
{
stream.CopyTo(ms);
byte[] romData = ms.ToArray();
// 4. Pass the raw bytes to our universal loader
LoadRomDataAndStart(romData, cleanFileName, resourceName);
}
}
}
public static string[] GetFilesInResourceDirectory(string directoryPrefix)
@@ -443,7 +441,7 @@ namespace Desktop
_vramViewer.Show();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
@@ -532,5 +530,28 @@ namespace Desktop
turboModeToolStripMenuItem.Checked = !turboModeToolStripMenuItem.Checked;
isTurboMode = turboModeToolStripMenuItem.Checked ? true : false;
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show(
$"First full release of Parsons Master System Emulator 2026!\r\n\r\nFeatures (v1.0):\r\n\r\n" +
$" *Full compatibility with all Master System and Game Gear ROMs\r\n" +
$" *Full window scaling with fixed aspect ratio (SMS & GG)\r\n" +
$" *Full 4 channel SN76489 implememtation using NAudio\r\n" +
$" *SRAM auto save and load (Battery Backed RAM)\r\n" +
$" *Keyboard and XInput control pad support\r\n" +
$" *Comprehensive Debugger\r\n" +
$" *VRAM Viewer\r\n" +
$" *Single point Save State\r\n" +
$" *Turbo mode\r\n" +
$" *Includes a selection of commercial ROMs\r\n\r\n" +
$"Planned updates (v1.1):\r\n\r\n" +
$" *Architectural double buffering (prevent screen tear)\r\n" +
$" *Graphics shaders (scanlines etc...)\r\n" +
$" *Add multiple Save States per game\r\n\r\n\r\n" +
$"(c) Marc Parsons 2026","Parsons Master System 2026 v1.0",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}