初步实现GB即时存档
This commit is contained in:
parent
48f465c35e
commit
008a9bf6a5
@ -68,9 +68,9 @@ namespace Essgee.Emulation.CPU
|
||||
|
||||
if (AppEnvironment.EnableSuperSlowCPULogger)
|
||||
{
|
||||
logFile = @"D:\Temp\Essgee\log-lr35902.txt";
|
||||
numLogEntries = 0;
|
||||
logEntries = new string[2000];
|
||||
//logFile = @"D:\Temp\Essgee\log-lr35902.txt";
|
||||
//numLogEntries = 0;
|
||||
//logEntries = new string[2000];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,7 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
//TODO GB相机暂时不实现
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
{
|
||||
@ -31,11 +32,26 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
ramData = data.MemberData[nameof(ramData)];
|
||||
hasBattery = BitConverter.ToBoolean(data.MemberData[nameof(hasBattery)]);
|
||||
|
||||
romBank = data.MemberData[nameof(romBank)].First();
|
||||
ramBank = data.MemberData[nameof(ramBank)].First();
|
||||
ramEnable = BitConverter.ToBoolean(data.MemberData[nameof(ramEnable)]);
|
||||
bankingMode = data.MemberData[nameof(bankingMode)].First();
|
||||
//看是否还需要补存储字段
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(ramData)] = ramData;
|
||||
data.MemberData[nameof(hasBattery)] = BitConverter.GetBytes(hasBattery);
|
||||
//看是否还需要补存储字段
|
||||
data.MemberData[nameof(romBank)] = BitConverter.GetBytes(romBank);
|
||||
data.MemberData[nameof(ramBank)] = BitConverter.GetBytes(ramBank);
|
||||
data.MemberData[nameof(ramEnable)] = BitConverter.GetBytes(ramEnable);
|
||||
data.MemberData[nameof(bankingMode)] = BitConverter.GetBytes(bankingMode);
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
{
|
||||
@ -23,13 +24,25 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
}
|
||||
#region AxiState
|
||||
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
ramData = data.MemberData[nameof(ramData)];
|
||||
hasBattery = BitConverter.ToBoolean(data.MemberData[nameof(hasBattery)]);
|
||||
|
||||
romBank = data.MemberData[nameof(romBank)].First();
|
||||
ramEnable = BitConverter.ToBoolean(data.MemberData[nameof(ramEnable)]);
|
||||
//看是否还需要补存储字段
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(ramData)] = ramData;
|
||||
data.MemberData[nameof(hasBattery)] = BitConverter.GetBytes(hasBattery);
|
||||
//看是否还需要补存储字段
|
||||
data.MemberData[nameof(romBank)] = BitConverter.GetBytes(romBank);
|
||||
data.MemberData[nameof(ramEnable)] = BitConverter.GetBytes(ramEnable);
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -135,11 +135,26 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
ramData = data.MemberData[nameof(ramData)];
|
||||
hasBattery = BitConverter.ToBoolean(data.MemberData[nameof(hasBattery)]);
|
||||
hasRTC = BitConverter.ToBoolean(data.MemberData[nameof(hasRTC)]);
|
||||
|
||||
romBank = data.MemberData[nameof(romBank)].First();
|
||||
ramBank = data.MemberData[nameof(ramBank)].First();
|
||||
ramEnable = BitConverter.ToBoolean(data.MemberData[nameof(ramEnable)]);
|
||||
//看是否还需要补存储字段
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(ramData)] = ramData;
|
||||
data.MemberData[nameof(hasBattery)] = BitConverter.GetBytes(hasBattery);
|
||||
data.MemberData[nameof(hasRTC)] = BitConverter.GetBytes(hasRTC);
|
||||
//看是否还需要补存储字段
|
||||
data.MemberData[nameof(romBank)] = BitConverter.GetBytes(romBank);
|
||||
data.MemberData[nameof(ramBank)] = BitConverter.GetBytes(ramBank);
|
||||
data.MemberData[nameof(ramEnable)] = BitConverter.GetBytes(ramEnable);
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
{
|
||||
@ -34,11 +35,26 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
ramData = data.MemberData[nameof(ramData)];
|
||||
hasBattery = BitConverter.ToBoolean(data.MemberData[nameof(hasBattery)]);
|
||||
hasRumble = BitConverter.ToBoolean(data.MemberData[nameof(hasRumble)]);
|
||||
|
||||
romBank = BitConverter.ToUInt16(data.MemberData[nameof(romBank)]);
|
||||
ramBank = data.MemberData[nameof(ramBank)].First();
|
||||
ramEnable = BitConverter.ToBoolean(data.MemberData[nameof(ramEnable)]);
|
||||
//看是否还需要补存储字段
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(ramData)] = ramData;
|
||||
data.MemberData[nameof(hasBattery)] = BitConverter.GetBytes(hasBattery);
|
||||
data.MemberData[nameof(hasRumble)] = BitConverter.GetBytes(hasRumble);
|
||||
//看是否还需要补存储字段
|
||||
data.MemberData[nameof(romBank)] = BitConverter.GetBytes(romBank);
|
||||
data.MemberData[nameof(ramBank)] = BitConverter.GetBytes(ramBank);
|
||||
data.MemberData[nameof(ramEnable)] = BitConverter.GetBytes(ramEnable);
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
{
|
||||
@ -17,11 +18,17 @@ namespace Essgee.Emulation.Cartridges.Nintendo
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
ramData = data.MemberData[nameof(ramData)];
|
||||
hasBattery = BitConverter.ToBoolean(data.MemberData[nameof(hasBattery)]);
|
||||
//看是否还需要补存储字段
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(ramData)] = ramData;
|
||||
data.MemberData[nameof(hasBattery)] = BitConverter.GetBytes(hasBattery);
|
||||
//看是否还需要补存储字段
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -99,11 +99,12 @@ namespace Essgee.Emulation
|
||||
public (string Manufacturer, string Model, string DatFileName, double RefreshRate, double PixelAspectRatio, (string Name, string Description)[] RuntimeOptions) Information =>
|
||||
(emulator.ManufacturerName, emulator.ModelName, emulator.DatFilename, emulator.RefreshRate, emulator.PixelAspectRatio, emulator.RuntimeOptions);
|
||||
|
||||
public EmulatorHandler(Type type, Action<Exception> exceptionHandler = null)
|
||||
public EmulatorHandler(Type type, Action<Exception> exceptionHandler = null, IAxiEssgssStatusBytesCover statusBytesCover = null)
|
||||
{
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
|
||||
emulator = (IMachine)Activator.CreateInstance(type);
|
||||
AxiStatus.Init(statusBytesCover);
|
||||
}
|
||||
|
||||
public void SetConfiguration(IConfiguration config)
|
||||
|
@ -136,11 +136,93 @@ namespace Essgee.Emulation.Machines
|
||||
|
||||
public void LoadAxiStatus(AxiEssgssStatusData data)
|
||||
{
|
||||
//config 暂时不需要存什么?
|
||||
//configuration. = data.MemberData[nameof(configuration.)].ToEnum<TVStandard>();
|
||||
|
||||
if (data.MemberData.ContainsKey(nameof(bootstrap)))
|
||||
bootstrap = data.MemberData[nameof(bootstrap)];
|
||||
|
||||
cartridge.LoadAxiStatus(data.ClassData[nameof(cartridge)]);
|
||||
wram = data.MemberData[nameof(wram)];
|
||||
hram = data.MemberData[nameof(hram)];
|
||||
ie = data.MemberData[nameof(ie)].First();
|
||||
cpu.LoadAxiStatus(data.ClassData[nameof(cpu)]);
|
||||
video.LoadAxiStatus(data.ClassData[nameof(video)]);
|
||||
audio.LoadAxiStatus(data.ClassData[nameof(audio)]);
|
||||
|
||||
//看是否还需要补存储字段
|
||||
|
||||
|
||||
joypadRegister = data.MemberData[nameof(joypadRegister)].First();
|
||||
serialData = data.MemberData[nameof(serialData)].First();
|
||||
serialUseInternalClock = BitConverter.ToBoolean(data.MemberData[nameof(serialUseInternalClock)]);
|
||||
divider = data.MemberData[nameof(divider)].First();
|
||||
timerCounter = data.MemberData[nameof(timerCounter)].First();
|
||||
clockCycleCount = BitConverter.ToUInt16(data.MemberData[nameof(clockCycleCount)]);
|
||||
timerModulo = data.MemberData[nameof(timerModulo)].First();
|
||||
timerRunning = BitConverter.ToBoolean(data.MemberData[nameof(timerRunning)]);
|
||||
timerInputClock = data.MemberData[nameof(timerInputClock)].First();
|
||||
timerOverflow = BitConverter.ToBoolean(data.MemberData[nameof(timerOverflow)]);
|
||||
timerLoading = BitConverter.ToBoolean(data.MemberData[nameof(timerLoading)]);
|
||||
irqVBlank = BitConverter.ToBoolean(data.MemberData[nameof(irqVBlank)]);
|
||||
irqLCDCStatus = BitConverter.ToBoolean(data.MemberData[nameof(irqLCDCStatus)]);
|
||||
irqTimerOverflow = BitConverter.ToBoolean(data.MemberData[nameof(irqTimerOverflow)]);
|
||||
irqSerialIO = BitConverter.ToBoolean(data.MemberData[nameof(irqSerialIO)]);
|
||||
irqKeypad = BitConverter.ToBoolean(data.MemberData[nameof(irqKeypad)]);
|
||||
bootstrapDisabled = BitConverter.ToBoolean(data.MemberData[nameof(bootstrapDisabled)]);
|
||||
|
||||
|
||||
serialBitsCounter = BitConverter.ToInt32(data.MemberData[nameof(serialBitsCounter)]);
|
||||
serialCycles = BitConverter.ToInt32(data.MemberData[nameof(serialCycles)]);
|
||||
currentMasterClockCyclesInFrame = BitConverter.ToInt32(data.MemberData[nameof(currentMasterClockCyclesInFrame)]);
|
||||
totalMasterClockCyclesInFrame = BitConverter.ToInt32(data.MemberData[nameof(totalMasterClockCyclesInFrame)]);
|
||||
|
||||
ReconfigureSystem();
|
||||
}
|
||||
|
||||
public AxiEssgssStatusData SaveAxiStatus()
|
||||
{
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
|
||||
//config 暂时不需要存什么?
|
||||
//data.MemberData[nameof(configuration.TVStandard)] = configuration.TVStandard.ToByteArray();
|
||||
|
||||
if (bootstrap != null)
|
||||
data.MemberData[nameof(bootstrap)] = bootstrap;
|
||||
|
||||
data.ClassData[nameof(cartridge)] = cartridge.SaveAxiStatus();
|
||||
data.MemberData[nameof(wram)] = wram;
|
||||
data.MemberData[nameof(hram)] = hram;
|
||||
data.MemberData[nameof(ie)] = BitConverter.GetBytes(ie);
|
||||
data.ClassData[nameof(cpu)] = cpu.SaveAxiStatus();
|
||||
data.ClassData[nameof(video)] = video.SaveAxiStatus();
|
||||
data.ClassData[nameof(audio)] = audio.SaveAxiStatus();
|
||||
|
||||
//看是否还需要补存储字段
|
||||
|
||||
data.MemberData[nameof(joypadRegister)] = BitConverter.GetBytes(joypadRegister);
|
||||
data.MemberData[nameof(serialData)] = BitConverter.GetBytes(serialData);
|
||||
data.MemberData[nameof(serialUseInternalClock)] = BitConverter.GetBytes(serialUseInternalClock);
|
||||
data.MemberData[nameof(divider)] = BitConverter.GetBytes(divider);
|
||||
data.MemberData[nameof(timerCounter)] = BitConverter.GetBytes(timerCounter);
|
||||
data.MemberData[nameof(clockCycleCount)] = BitConverter.GetBytes(clockCycleCount);
|
||||
data.MemberData[nameof(timerModulo)] = BitConverter.GetBytes(timerModulo);
|
||||
data.MemberData[nameof(timerRunning)] = BitConverter.GetBytes(timerRunning);
|
||||
data.MemberData[nameof(timerInputClock)] = BitConverter.GetBytes(timerInputClock);
|
||||
data.MemberData[nameof(timerOverflow)] = BitConverter.GetBytes(timerOverflow);
|
||||
data.MemberData[nameof(timerLoading)] = BitConverter.GetBytes(timerLoading);
|
||||
data.MemberData[nameof(irqVBlank)] = BitConverter.GetBytes(irqVBlank);
|
||||
data.MemberData[nameof(irqLCDCStatus)] = BitConverter.GetBytes(irqLCDCStatus);
|
||||
data.MemberData[nameof(irqTimerOverflow)] = BitConverter.GetBytes(irqTimerOverflow);
|
||||
data.MemberData[nameof(irqSerialIO)] = BitConverter.GetBytes(irqSerialIO);
|
||||
data.MemberData[nameof(irqKeypad)] = BitConverter.GetBytes(irqKeypad);
|
||||
data.MemberData[nameof(bootstrapDisabled)] = BitConverter.GetBytes(bootstrapDisabled);
|
||||
|
||||
data.MemberData[nameof(serialBitsCounter)] = BitConverter.GetBytes(serialBitsCounter);
|
||||
data.MemberData[nameof(serialCycles)] = BitConverter.GetBytes(serialCycles);
|
||||
data.MemberData[nameof(currentMasterClockCyclesInFrame)] = BitConverter.GetBytes(currentMasterClockCyclesInFrame);
|
||||
data.MemberData[nameof(totalMasterClockCyclesInFrame)] = BitConverter.GetBytes(totalMasterClockCyclesInFrame);
|
||||
|
||||
return data;
|
||||
}
|
||||
#endregion
|
||||
|
@ -301,7 +301,9 @@ namespace Essgee.Emulation.Machines
|
||||
{
|
||||
configuration.Region = data.MemberData[nameof(configuration.Region)].ToEnum<Region>();
|
||||
|
||||
bootstrap.LoadAxiStatus(data.ClassData[nameof(bootstrap)]);
|
||||
if (data.ClassData.ContainsKey(nameof(bootstrap)))
|
||||
bootstrap.LoadAxiStatus(data.ClassData[nameof(bootstrap)]);
|
||||
|
||||
cartridge.LoadAxiStatus(data.ClassData[nameof(cartridge)]);
|
||||
wram = data.MemberData[nameof(wram)];
|
||||
cpu.LoadAxiStatus(data.ClassData[nameof(cpu)]);
|
||||
@ -327,7 +329,9 @@ namespace Essgee.Emulation.Machines
|
||||
AxiEssgssStatusData data = new AxiEssgssStatusData();
|
||||
data.MemberData[nameof(configuration.Region)] = configuration.Region.ToByteArray();
|
||||
|
||||
data.ClassData[nameof(bootstrap)] = bootstrap.SaveAxiStatus();
|
||||
if (bootstrap != null)
|
||||
data.ClassData[nameof(bootstrap)] = bootstrap.SaveAxiStatus();
|
||||
|
||||
data.ClassData[nameof(cartridge)] = cartridge.SaveAxiStatus();
|
||||
data.MemberData[nameof(wram)] = wram;
|
||||
data.ClassData[nameof(cpu)] = cpu.SaveAxiStatus();
|
||||
|
@ -12,6 +12,7 @@ public class AxiEssgssStatusData
|
||||
public Dictionary<string, AxiEssgssStatusData> ClassData = new Dictionary<string, AxiEssgssStatusData>();
|
||||
}
|
||||
|
||||
|
||||
[Serializable]
|
||||
public class AxiEssgssStatusData_2DArray
|
||||
{
|
||||
@ -30,25 +31,16 @@ public class AxiEssgssStatusData_2DArray
|
||||
return array1D.CreateByteArray2D(rows, cols);
|
||||
}
|
||||
}
|
||||
public static class AxiEssgssStatusDataExtention
|
||||
internal static class AxiEssgssStatusDataExtention
|
||||
{
|
||||
public static byte[] ToByteArray(this AxiEssgssStatusData data)
|
||||
internal static byte[] ToByteArray(this AxiEssgssStatusData data)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
formatter.Serialize(ms, data);
|
||||
return ms.ToArray();
|
||||
}
|
||||
return AxiStatus.saveCover.ToByteArray(data);
|
||||
}
|
||||
|
||||
public static AxiEssgssStatusData ToAxiEssgssStatusData(this byte[] byteArray)
|
||||
internal static AxiEssgssStatusData ToAxiEssgssStatusData(this byte[] byteArray)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream(byteArray))
|
||||
{
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
return (AxiEssgssStatusData)formatter.Deserialize(ms);
|
||||
}
|
||||
return AxiStatus.saveCover.ToAxiEssgssStatusData(byteArray);
|
||||
}
|
||||
}
|
||||
public interface IAxiStatus
|
||||
@ -57,8 +49,19 @@ public interface IAxiStatus
|
||||
public AxiEssgssStatusData SaveAxiStatus();
|
||||
}
|
||||
|
||||
public interface IAxiEssgssStatusBytesCover
|
||||
{
|
||||
public byte[] ToByteArray(AxiEssgssStatusData data);
|
||||
public AxiEssgssStatusData ToAxiEssgssStatusData(byte[] byteArray);
|
||||
}
|
||||
|
||||
internal static class AxiStatus
|
||||
{
|
||||
public static IAxiEssgssStatusBytesCover saveCover { get; private set; }
|
||||
public static void Init(IAxiEssgssStatusBytesCover coverter)
|
||||
{
|
||||
saveCover = coverter;
|
||||
}
|
||||
// 将任意枚举数组转换为byte[]
|
||||
public static byte[] ToByteArray<TEnum>(this TEnum[] enumArray) where TEnum : struct, Enum
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user