Tidy Up
This commit is contained in:
@@ -33,7 +33,9 @@ namespace Core.Audio
|
|||||||
0.1584f, 0.1258f, 0.1000f, 0.0794f, 0.0630f, 0.0501f, 0.0398f, 0.0f
|
0.1584f, 0.1258f, 0.1000f, 0.0794f, 0.0630f, 0.0501f, 0.0398f, 0.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
public SmsApu()
|
public SmsApu()
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
{
|
{
|
||||||
Registers[1] = 0x0F;
|
Registers[1] = 0x0F;
|
||||||
Registers[3] = 0x0F;
|
Registers[3] = 0x0F;
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ namespace Core.Io
|
|||||||
{
|
{
|
||||||
public class SmsIoBus : IIoBus
|
public class SmsIoBus : IIoBus
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
public SmsVdp VideoProcessor { get; set; }
|
public SmsVdp VideoProcessor { get; set; }
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
public SmsApu AudioProcessor { get; set; }
|
public SmsApu AudioProcessor { get; set; }
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
|
|
||||||
// Joypad State (0xFF means no buttons pressed - the SMS uses Active-Low logic!)
|
// Joypad State (0xFF means no buttons pressed - the SMS uses Active-Low logic!)
|
||||||
public byte Joypad1Keyboard = 0xFF;
|
public byte Joypad1Keyboard = 0xFF;
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<StartupObject>Desktop.Program</StartupObject>
|
<StartupObject>Desktop.Program</StartupObject>
|
||||||
<AssemblyName>Parsons Master System</AssemblyName>
|
<AssemblyName>Parsons Master System 2026</AssemblyName>
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||||
<Title>Sega Master System EMulator 2026</Title>
|
<Title>Sega Master System EMulator 2026</Title>
|
||||||
<Version>0.9</Version>
|
<Version>1.0</Version>
|
||||||
<Authors>Marc Parsons</Authors>
|
<Authors>Marc Parsons</Authors>
|
||||||
<Company>Parsons Limited</Company>
|
<Company>Parsons Limited</Company>
|
||||||
<Description>Parsons Master System 2026</Description>
|
<Description>Parsons Master System 2026</Description>
|
||||||
|
|||||||
142
Desktop/Form1.cs
142
Desktop/Form1.cs
@@ -34,12 +34,18 @@ namespace Desktop
|
|||||||
set { if (_machine != null) _machine.Breakpoint = value; }
|
set { if (_machine != null) _machine.Breakpoint = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
public ParsonsForm1()
|
public ParsonsForm1()
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.KeyPreview = true;
|
this.KeyPreview = true;
|
||||||
|
#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
|
||||||
this.KeyDown += Form1_KeyDown;
|
this.KeyDown += Form1_KeyDown;
|
||||||
|
#pragma warning restore CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
|
||||||
|
#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
|
||||||
this.KeyUp += Form1_KeyUp;
|
this.KeyUp += Form1_KeyUp;
|
||||||
|
#pragma warning restore CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).
|
||||||
this.DoubleBuffered = true;
|
this.DoubleBuffered = true;
|
||||||
this.ResizeRedraw = true;
|
this.ResizeRedraw = true;
|
||||||
}
|
}
|
||||||
@@ -115,42 +121,7 @@ namespace Desktop
|
|||||||
e.Graphics.DrawImage(_screenBitmap, destRect, sourceRect, GraphicsUnit.Pixel);
|
e.Graphics.DrawImage(_screenBitmap, destRect, sourceRect, GraphicsUnit.Pixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//protected override void OnPaint(PaintEventArgs e)
|
|
||||||
//{
|
|
||||||
// base.OnPaint(e);
|
|
||||||
|
|
||||||
// if (_screenBitmap != null && menuStrip1 != null)
|
|
||||||
// {
|
|
||||||
// // 1. Maintain perfect, chunky retro pixels
|
|
||||||
// e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
|
||||||
// e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
|
|
||||||
|
|
||||||
// // 2. Calculate the actual usable window space
|
|
||||||
// int topOffset = menuStrip1.Height;
|
|
||||||
// int availableWidth = this.ClientSize.Width;
|
|
||||||
// int availableHeight = this.ClientSize.Height - topOffset;
|
|
||||||
|
|
||||||
// // 3. Calculate the maximum scale factor that fits perfectly
|
|
||||||
// float scaleX = (float)availableWidth / 256f;
|
|
||||||
// float scaleY = (float)availableHeight / 192f;
|
|
||||||
|
|
||||||
// // Pick the smaller scale so the image never bleeds off the edge
|
|
||||||
// float scale = Math.Min(scaleX, scaleY);
|
|
||||||
|
|
||||||
// // 4. Calculate the new physical pixel dimensions
|
|
||||||
// int newWidth = (int)(256 * scale);
|
|
||||||
// int newHeight = (int)(192 * scale);
|
|
||||||
|
|
||||||
// // 5. Center the image (Letterboxing / Pillarboxing)
|
|
||||||
// int offsetX = (availableWidth - newWidth) / 2;
|
|
||||||
// int offsetY = topOffset + ((availableHeight - newHeight) / 2);
|
|
||||||
|
|
||||||
// Rectangle renderArea = new Rectangle(offsetX, offsetY, newWidth, newHeight);
|
|
||||||
|
|
||||||
// // 6. Draw the scaled image
|
|
||||||
// e.Graphics.DrawImage(_screenBitmap, renderArea);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public void StartEmulator()
|
public void StartEmulator()
|
||||||
{
|
{
|
||||||
@@ -204,7 +175,9 @@ namespace Desktop
|
|||||||
if (_machine.Breakpoint.HasValue && _machine.Cpu.PC == _machine.Breakpoint.Value)
|
if (_machine.Breakpoint.HasValue && _machine.Cpu.PC == _machine.Breakpoint.Value)
|
||||||
{
|
{
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
|
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||||
BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { _debugger?.uiUpdateTimer_Tick(null, EventArgs.Empty); });
|
BeginInvoke((System.Windows.Forms.MethodInvoker)delegate { _debugger?.uiUpdateTimer_Tick(null, EventArgs.Empty); });
|
||||||
|
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +275,9 @@ namespace Desktop
|
|||||||
{
|
{
|
||||||
// Don't try to save if a game hasn't been loaded yet!
|
// Don't try to save if a game hasn't been loaded yet!
|
||||||
if (string.IsNullOrEmpty(_currentRomName) || _currentRomName == "No ROM")
|
if (string.IsNullOrEmpty(_currentRomName) || _currentRomName == "No ROM")
|
||||||
|
#pragma warning disable CS8603 // Possible null reference return.
|
||||||
return null;
|
return null;
|
||||||
|
#pragma warning restore CS8603 // Possible null reference return.
|
||||||
|
|
||||||
// Application.StartupPath is the exact folder containing your .exe
|
// Application.StartupPath is the exact folder containing your .exe
|
||||||
string exeFolder = Application.StartupPath;
|
string exeFolder = Application.StartupPath;
|
||||||
@@ -324,38 +299,85 @@ namespace Desktop
|
|||||||
|
|
||||||
private void PopulateIncludedRomsMenu()
|
private void PopulateIncludedRomsMenu()
|
||||||
{
|
{
|
||||||
string romsDirectory = @"C:\Parsons\Local Code Projects\ParsonsMasterSystem2026\Desktop\ROMS\";
|
string romsDirectory = "Desktop.ROMS";
|
||||||
|
string[] files = GetFilesInResourceDirectory(romsDirectory);
|
||||||
|
|
||||||
if (Directory.Exists(romsDirectory))
|
foreach (string resourceName in files)
|
||||||
{
|
{
|
||||||
string[] romFiles = Directory.GetFiles(romsDirectory, "*.sms");
|
// 1. Strip the "Desktop.ROMS." prefix
|
||||||
foreach (string file in romFiles)
|
string cleanFileName = resourceName.Replace("Desktop.ROMS.", "");
|
||||||
|
|
||||||
|
// 2. Strip the extension for a beautiful menu item (e.g. "Sonic")
|
||||||
|
string menuName = Path.GetFileNameWithoutExtension(cleanFileName);
|
||||||
|
|
||||||
|
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(menuName);
|
||||||
|
|
||||||
|
// 3. Point the click event to our new extraction helper!
|
||||||
|
romMenuItem.Click += (sender, e) => ExtractAndLoadEmbeddedRom(resourceName);
|
||||||
|
|
||||||
|
// 4. Sort into the correct menu based on extension!
|
||||||
|
if (resourceName.EndsWith(".gg", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Create a new dropdown item for each .sms file it finds
|
|
||||||
string romName = Path.GetFileNameWithoutExtension(file);
|
|
||||||
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(romName);
|
|
||||||
|
|
||||||
// When clicked, pass the file path to our helper method
|
|
||||||
romMenuItem.Click += (sender, e) => LoadRomAndStart(file);
|
|
||||||
|
|
||||||
// Add it to the "Included" submenu (make sure the name matches your designer element!)
|
|
||||||
masterSystemToolStripMenuItem.DropDownItems.Add(romMenuItem);
|
|
||||||
}
|
|
||||||
romFiles = Directory.GetFiles(romsDirectory, "*.gg");
|
|
||||||
foreach (string file in romFiles)
|
|
||||||
{
|
|
||||||
// Create a new dropdown item for each .gg file it finds
|
|
||||||
string romName = Path.GetFileNameWithoutExtension(file);
|
|
||||||
ToolStripMenuItem romMenuItem = new ToolStripMenuItem(romName);
|
|
||||||
|
|
||||||
// When clicked, pass the file path to the helper method
|
|
||||||
romMenuItem.Click += (sender, e) => LoadRomAndStart(file);
|
|
||||||
gameGearToolStripMenuItem.DropDownItems.Add(romMenuItem);
|
gameGearToolStripMenuItem.DropDownItems.Add(romMenuItem);
|
||||||
}
|
}
|
||||||
|
else if (resourceName.EndsWith(".sms", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
masterSystemToolStripMenuItem.DropDownItems.Add(romMenuItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExtractAndLoadEmbeddedRom(string resourceName)
|
||||||
|
{
|
||||||
|
// 1. Strip off the ugly "Desktop.ROMS." prefix to get the real file name
|
||||||
|
string cleanFileName = resourceName.Replace("Desktop.ROMS.", "");
|
||||||
|
|
||||||
|
// 2. Create a physical path right next to your emulator .exe
|
||||||
|
string physicalPath = Path.Combine(Application.StartupPath, cleanFileName);
|
||||||
|
|
||||||
|
// 3. If we haven't extracted this game yet, extract it now!
|
||||||
|
if (!File.Exists(physicalPath))
|
||||||
|
{
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Now that it is a REAL file on the hard drive, pass it to your normal loader!
|
||||||
|
LoadRomAndStart(physicalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetFilesInResourceDirectory(string directoryPrefix)
|
||||||
|
{
|
||||||
|
// Get the assembly containing the embedded resources.
|
||||||
|
// Change this if your resources are in a different project/assembly.
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
// Ensure the prefix ends with a dot so we don't accidentally match
|
||||||
|
// similarly named folders (e.g., matching "Folder" but not "FolderTwo")
|
||||||
|
if (!directoryPrefix.EndsWith("."))
|
||||||
|
{
|
||||||
|
directoryPrefix += ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all resource names and filter by our "directory" prefix
|
||||||
|
string[] allResources = assembly.GetManifestResourceNames();
|
||||||
|
|
||||||
|
string[] filesInDirectory = allResources
|
||||||
|
.Where(resource => resource.StartsWith(directoryPrefix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return filesInDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
private void selectROMToolStripMenuItem_Click(object sender, EventArgs e)
|
private void selectROMToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
using (OpenFileDialog ofd = new OpenFileDialog())
|
using (OpenFileDialog ofd = new OpenFileDialog())
|
||||||
|
|||||||
Reference in New Issue
Block a user