Added SRAM save game functionality

This commit is contained in:
2026-05-15 00:19:45 +01:00
parent c416bea9ac
commit 787e403232
3 changed files with 84 additions and 6 deletions

View File

@@ -23,6 +23,7 @@ namespace Core.Memory
// A flag to handle cartridges that don't use paging (like early 32KB games) // A flag to handle cartridges that don't use paging (like early 32KB games)
private bool _isCartridgeLoaded = false; private bool _isCartridgeLoaded = false;
public bool SramUsed { get; private set; } = false;
public void LoadCartridge(byte[] romData) public void LoadCartridge(byte[] romData)
{ {
@@ -57,7 +58,7 @@ namespace Core.Memory
if ((_mapperControl & 0x08) != 0) if ((_mapperControl & 0x08) != 0)
{ {
int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0; int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
int ramOffset = (ramBank * 0x4000) + (address & 0x3FFF); int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
return _cartridgeRam[ramOffset]; return _cartridgeRam[ramOffset];
} }
@@ -139,8 +140,9 @@ namespace Core.Memory
// Bypass the lock if they are trying to save their game! // Bypass the lock if they are trying to save their game!
if (address >= 0x8000 && (_mapperControl & 0x08) != 0) if (address >= 0x8000 && (_mapperControl & 0x08) != 0)
{ {
SramUsed = true;
int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0; int ramBank = (_mapperControl & 0x04) != 0 ? 1 : 0;
int ramOffset = (ramBank * 0x4000) + (address & 0x3FFF); int ramOffset = (ramBank * 0x4000) + (address & 0x1FFF);
_cartridgeRam[ramOffset] = value; _cartridgeRam[ramOffset] = value;
return; return;
} }
@@ -196,11 +198,37 @@ namespace Core.Memory
return _cartridgeRom[absoluteAddress]; return _cartridgeRom[absoluteAddress];
} }
public void LoadSaveData(string filePath)
{
if (System.IO.File.Exists(filePath))
{
byte[] saveData = System.IO.File.ReadAllBytes(filePath);
Array.Copy(saveData, _cartridgeRam, Math.Min(saveData.Length, _cartridgeRam.Length));
SramUsed = true; // We loaded a save, so it's active!
}
else
{
for (int i = 0; i < _cartridgeRam.Length; i++)
{
_cartridgeRam[i] = 0xFF;
}
SramUsed = false;
}
}
public void SaveSaveData(string filePath)
{
// Only write a file to the hard drive if the game actually used the Save RAM!
if (SramUsed)
{
System.IO.File.WriteAllBytes(filePath, _cartridgeRam);
}
}
public void CleanRAMData() public void CleanRAMData()
{ {
Array.Clear(_workRam, 0, _workRam.Length); Array.Clear(_workRam, 0, _workRam.Length);
Array.Clear(_cartridgeRam, 0, _cartridgeRam.Length); _mapperControl = 0;
} }
} }
} }

View File

@@ -22,6 +22,7 @@ namespace Desktop
public double FrameTime { get; private set; } = 0; public double FrameTime { get; private set; } = 0;
public double FramesPerSecond { get; private set; } = 0; public double FramesPerSecond { get; private set; } = 0;
private string _currentRomName = "No ROM"; private string _currentRomName = "No ROM";
private string _currentRomPath = "";
private Stopwatch _stopwatch = new System.Diagnostics.Stopwatch(); private Stopwatch _stopwatch = new System.Diagnostics.Stopwatch();
public bool IsRunning { get; private set; } = false; public bool IsRunning { get; private set; } = false;
@@ -181,7 +182,6 @@ namespace Desktop
{ {
IsRunning = false; IsRunning = false;
} }
private async void LoadRomAndStart(string filePath) private async void LoadRomAndStart(string filePath)
{ {
StopEmulator(); StopEmulator();
@@ -190,20 +190,59 @@ namespace Desktop
await _emulatorTask; await _emulatorTask;
} }
// 1. SAVE THE PREVIOUS GAME!
SaveCurrentSram();
// 2. Load the file // 2. Load the file
byte[] rom = File.ReadAllBytes(filePath); byte[] rom = File.ReadAllBytes(filePath);
// 3. Jam it into the Sega Mapper // 3. Jam it into the Sega Mapper
_machine.LoadCartridge(rom); _machine.LoadCartridge(rom);
// 4. Update the path tracking
_currentRomPath = filePath;
_currentRomName = Path.GetFileNameWithoutExtension(filePath); _currentRomName = Path.GetFileNameWithoutExtension(filePath);
this.Text = $"Parsons Master System - {_currentRomName}"; this.Text = $"Parsons Master System - {_currentRomName}";
// 5. Turn the power on! // 5. LOAD THE NEW SAVE DATA!
string savPath = Path.ChangeExtension(_currentRomPath, ".sav");
_machine.MemoryBus.LoadSaveData(savPath);
// 6. Turn the power on!
StartEmulator(); StartEmulator();
} }
//private async void LoadRomAndStart(string filePath)
//{
// StopEmulator();
// if (_emulatorTask != null)
// {
// await _emulatorTask;
// }
// // 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();
//}
private void SaveCurrentSram()
{
if (!string.IsNullOrEmpty(_currentRomPath) && _machine != null)
{
// Swaps ".sms" for ".sav"
string savPath = Path.ChangeExtension(_currentRomPath, ".sav");
_machine.MemoryBus.SaveSaveData(savPath);
}
}
private void PopulateIncludedRomsMenu() private void PopulateIncludedRomsMenu()
{ {
// The folder you used for Golden Axe Warrior // The folder you used for Golden Axe Warrior
@@ -264,7 +303,7 @@ namespace Desktop
private void exitToolStripMenuItem_Click(object sender, EventArgs e) private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{ {
Environment.Exit(0); this.Close();
} }
private void Form1_KeyDown(object sender, KeyEventArgs e) private void Form1_KeyDown(object sender, KeyEventArgs e)
@@ -308,6 +347,7 @@ namespace Desktop
private void ParsonsForm1_FormClosing(object sender, FormClosingEventArgs e) private void ParsonsForm1_FormClosing(object sender, FormClosingEventArgs e)
{ {
IsRunning = false; IsRunning = false;
SaveCurrentSram();
_audioPlayer?.Stop(); _audioPlayer?.Stop();
} }
} }

10
Desktop/ROMS/zexdoc.sav Normal file

File diff suppressed because one or more lines are too long