diff --git a/BizHawk.Emulation/CPUs/Native68000/Musashi.cs b/BizHawk.Emulation/CPUs/Native68000/Musashi.cs index d579287348..d661d3cc15 100644 --- a/BizHawk.Emulation/CPUs/Native68000/Musashi.cs +++ b/BizHawk.Emulation/CPUs/Native68000/Musashi.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.IO; namespace Native68000 { @@ -48,6 +49,9 @@ namespace Native68000 [DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int QueryCpuState(int regcode); + [DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void SetCpuState(int regcode, int value); + [DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int GetCyclesRemaining(); @@ -72,5 +76,17 @@ namespace Native68000 public static int PC { get { return QueryCpuState(16); } } public static int SR { get { return QueryCpuState(17); } } public static int SP { get { return QueryCpuState(18); } } + + public static void SaveStateBinary(BinaryWriter writer) + { + for (int i=0; i<31; i++) + writer.Write(QueryCpuState(i)); + } + + public static void LoadStateBinary(BinaryReader reader) + { + for (int i = 0; i < 31; i++) + SetCpuState(i, reader.ReadInt32()); + } } } \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/PC Engine/Compat.txt b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt index 340fca4a9a..1ffc03928d 100644 --- a/BizHawk.Emulation/Consoles/PC Engine/Compat.txt +++ b/BizHawk.Emulation/Consoles/PC Engine/Compat.txt @@ -12,6 +12,7 @@ Still some lesser issues with cancelling a fadeout. Otherwise CDDA is working no - JANSHIN DENSETSU sets the T flag prior to an LDA instruction; MANY TIMES (ie it doesnt seem to be an accident). Unclear if T flag actually affects LDA instruction. +- Gradius II sets T flag prior to an STZ instruction. Unclear if T-flag affects STZ instruction. - Ryuuko no Ken is all messed up, and I don't super care :| - Record of Lodoss War wont start game from title screen - Valis: Screen is black during entire intro section diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs index f545367277..5c8c5f3659 100644 --- a/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/GenVDP.cs @@ -522,6 +522,39 @@ int orig_addr = VdpDataAddr; WriteVdpRegister(i, Registers[i]); } + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(VRAM); + writer.Write(CRAM); + writer.Write(VSRAM); + writer.Write(Registers); + + writer.Write(ControlWordPending); + writer.Write(DmaFillModePending); + writer.Write(VdpDataAddr); + writer.Write(VdpDataCode); + } + + public void LoadStateBinary(BinaryReader reader) + { + VRAM = reader.ReadBytes(VRAM.Length); + CRAM = reader.ReadUInt16s(CRAM.Length); + VSRAM = reader.ReadUInt16s(VSRAM.Length); + Registers = reader.ReadBytes(Registers.Length); + + ControlWordPending = reader.ReadBoolean(); + DmaFillModePending = reader.ReadBoolean(); + VdpDataAddr = reader.ReadUInt16(); + VdpDataCode = reader.ReadByte(); + + for (int i = 0; i < CRAM.Length; i++) + ProcessPalette(i); + for (int i = 0; i < VRAM.Length; i++) + UpdatePatternBuffer(i); + for (int i = 0; i < Registers.Length; i++) + WriteVdpRegister(i, Registers[i]); + } + #endregion } } \ No newline at end of file diff --git a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs index 7d8207e7ce..06a6a58939 100644 --- a/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs +++ b/BizHawk.Emulation/Consoles/Sega/Genesis/Genesis.cs @@ -271,7 +271,7 @@ namespace BizHawk.Emulation.Consoles.Sega public void SaveStateText(TextWriter writer) { - writer.WriteLine("[MegaDrive]"); + /*writer.WriteLine("[MegaDrive]"); MainCPU.SaveStateText(writer, "Main68K"); SoundCPU.SaveStateText(writer); PSG.SaveStateText(writer); @@ -283,14 +283,12 @@ namespace BizHawk.Emulation.Consoles.Sega Ram.SaveAsHex(writer); writer.Write("Z80RAM "); Z80Ram.SaveAsHex(writer); - - - writer.WriteLine("[/MegaDrive]"); + writer.WriteLine("[/MegaDrive]");*/ } public void LoadStateText(TextReader reader) { - while (true) + /*while (true) { string[] args = reader.ReadLine().Split(' '); if (args[0].Trim() == "") continue; @@ -316,22 +314,53 @@ namespace BizHawk.Emulation.Consoles.Sega VDP.LoadStateText(reader); else Console.WriteLine("Skipping unrecognized identifier " + args[0]); - } + }*/ } public void SaveStateBinary(BinaryWriter writer) { - //throw new NotImplementedException(); + Musashi.SaveStateBinary(writer); // 124 + SoundCPU.SaveStateBinary(writer); // 46 + PSG.SaveStateBinary(writer); // 15 + VDP.SaveStateBinary(writer); // 65781 + YM2612.SaveStateBinary(writer); // 35 + + writer.Write(Ram); // 65535 + writer.Write(Z80Ram); // 8192 + + writer.Write(Frame); // 4 + // lag counter crap TODO + writer.Write(M68000HasZ80Bus); // 1 + writer.Write(Z80Reset); // 1 + + // TODO Saveram/EEPROM } public void LoadStateBinary(BinaryReader reader) { - //throw new NotImplementedException(); + Musashi.LoadStateBinary(reader); + SoundCPU.LoadStateBinary(reader); + PSG.LoadStateBinary(reader); + VDP.LoadStateBinary(reader); + YM2612.LoadStateBinary(reader); + + Ram = reader.ReadBytes(Ram.Length); + Z80Ram = reader.ReadBytes(Z80Ram.Length); + + Frame = reader.ReadInt32(); + M68000HasZ80Bus = reader.ReadBoolean(); + Z80Reset = reader.ReadBoolean(); } public byte[] SaveStateBinary() { - return new byte[0]; + var buf = new byte[141485]; + var stream = new MemoryStream(buf); + var writer = new BinaryWriter(stream); + SaveStateBinary(writer); + //Console.WriteLine("buf len = {0}", stream.Position); + writer.Close(); + return buf; } IList memoryDomains; diff --git a/BizHawk.Emulation/Sound/YM2612.cs b/BizHawk.Emulation/Sound/YM2612.cs index e9cfb9a161..c70067f5d1 100644 --- a/BizHawk.Emulation/Sound/YM2612.cs +++ b/BizHawk.Emulation/Sound/YM2612.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.Collections.Generic; +using System.IO; namespace BizHawk.Emulation.Sound { @@ -1053,11 +1054,6 @@ namespace BizHawk.Emulation.Sound return value - Math.Floor(value); } - /// - /// basic linear audio resampler. sampling rate is inferred from buffer sizes - /// - /// stereo s16 - /// stereo s16 static void LinearDownsampler(short[] input, short[] output) { double samplefactor = input.Length / (double)output.Length; @@ -1162,5 +1158,134 @@ namespace BizHawk.Emulation.Sound public void DiscardSamples() { } public int MaxVolume { get; set; } + + // ==================================================================================== + // Save States + // ==================================================================================== + + public void SaveStateBinary(BinaryWriter writer) + { + writer.Write(TimerAPeriod); + writer.Write(TimerBPeriod); + writer.Write(TimerATripped); + writer.Write(TimerBTripped); + writer.Write(TimerAResetClock); + writer.Write(TimerBResetClock); + writer.Write(TimerALastReset); + writer.Write(TimerBLastReset); + writer.Write(TimerControl27); + writer.Write(egDivisorCounter); + writer.Write(egCycleCounter); + + writer.Write(PartSelect); + writer.Write(RegisterSelect); + writer.Write(DacEnable); + writer.Write(DacValue); + + for (int i = 0; i < 6; i++) + ChannelSaveStateBinary(writer, Channels[i]); + } + + public void LoadStateBinary(BinaryReader reader) + { + TimerAPeriod = reader.ReadInt32(); + TimerBPeriod = reader.ReadInt32(); + TimerATripped = reader.ReadBoolean(); + TimerBTripped = reader.ReadBoolean(); + TimerAResetClock = reader.ReadInt32(); + TimerBResetClock = reader.ReadInt32(); + TimerALastReset = reader.ReadInt32(); + TimerBLastReset = reader.ReadInt32(); + TimerControl27 = reader.ReadByte(); + egDivisorCounter = reader.ReadInt32(); + egCycleCounter = reader.ReadInt32(); + + PartSelect = reader.ReadByte(); + RegisterSelect = reader.ReadByte(); + DacEnable = reader.ReadBoolean(); + DacValue = reader.ReadByte(); + + for (int i = 0; i < 6; i++) + ChannelLoadStateBinary(reader, Channels[i]); + } + + void ChannelSaveStateBinary(BinaryWriter writer, Channel c) + { + // TODO reduce size of state via casting + writer.Write(c.FrequencyNumber); + writer.Write(c.Block); + writer.Write(c.Feedback); + writer.Write(c.Algorithm); + writer.Write(c.SpecialMode); + writer.Write(c.LeftOutput); + writer.Write(c.RightOutput); + writer.Write(c.AMS_AmplitudeModulationSensitivity); + writer.Write(c.FMS_FrequencyModulationSensitivity); + + for (int i = 0; i < 4; i++) + OperatorSaveStateBinary(writer, c.Operators[i]); + } + + void ChannelLoadStateBinary(BinaryReader reader, Channel c) + { + c.FrequencyNumber = reader.ReadInt32(); + c.Block = reader.ReadInt32(); + c.Feedback = reader.ReadInt32(); + c.Algorithm = reader.ReadInt32(); + c.SpecialMode = reader.ReadBoolean(); + c.LeftOutput = reader.ReadBoolean(); + c.RightOutput = reader.ReadBoolean(); + c.AMS_AmplitudeModulationSensitivity = reader.ReadInt32(); + c.FMS_FrequencyModulationSensitivity = reader.ReadInt32(); + + for (int i = 0; i < 4; i++) + OperatorLoadStateBinary(reader, c.Operators[i]); + } + + void OperatorSaveStateBinary(BinaryWriter writer, Operator op) + { + // TODO, size of states could be shrunken by using casts. + writer.Write(op.TL_TotalLevel); + writer.Write(op.SL_SustainLevel); + writer.Write(op.AR_AttackRate); + writer.Write(op.DR_DecayRate); + writer.Write(op.SR_SustainRate); + writer.Write(op.RR_ReleaseRate); + writer.Write(op.KS_KeyScale); + writer.Write(op.SSG_EG); + writer.Write(op.DT_Detune); + writer.Write(op.MUL_Multiple); + writer.Write(op.AM_AmplitudeModulation); + writer.Write(op.FrequencyNumber); + writer.Write(op.Block); + writer.Write(op.KeyCode); + writer.Write(op.Rks); + writer.Write(op.PhaseCounter); + writer.Write((byte)op.EnvelopeState); + writer.Write(op.EgAttenuation); + } + + void OperatorLoadStateBinary(BinaryReader reader, Operator op) + { + op.TL_TotalLevel = reader.ReadInt32(); + op.SL_SustainLevel = reader.ReadInt32(); + op.AR_AttackRate = reader.ReadInt32(); + op.DR_DecayRate = reader.ReadInt32(); + op.SR_SustainRate = reader.ReadInt32(); + op.RR_ReleaseRate = reader.ReadInt32(); + op.KS_KeyScale = reader.ReadInt32(); + op.SSG_EG = reader.ReadInt32(); + op.DT_Detune = reader.ReadInt32(); + op.MUL_Multiple = reader.ReadInt32(); + op.AM_AmplitudeModulation = reader.ReadBoolean(); + + op.FrequencyNumber = reader.ReadInt32(); + op.Block = reader.ReadInt32(); + op.KeyCode = reader.ReadInt32(); + op.Rks = reader.ReadInt32(); + op.PhaseCounter = reader.ReadInt32(); + op.EnvelopeState = (EnvelopeState)Enum.ToObject(typeof(EnvelopeState), reader.ReadByte()); + op.EgAttenuation = reader.ReadInt32(); + } } } \ No newline at end of file diff --git a/BizHawk.Emulation/Util.cs b/BizHawk.Emulation/Util.cs index 44e28833e7..08f8aa0270 100644 --- a/BizHawk.Emulation/Util.cs +++ b/BizHawk.Emulation/Util.cs @@ -305,7 +305,7 @@ namespace BizHawk bw.Write(buffer[i]); } - public static int[] ReadInts(this BinaryReader br, int num) + public static int[] ReadInt32s(this BinaryReader br, int num) { int[] ret = new int[num]; for (int i = 0; i < num; i++) @@ -313,7 +313,7 @@ namespace BizHawk return ret; } - public static short[] ReadShorts(this BinaryReader br, int num) + public static short[] ReadInt16s(this BinaryReader br, int num) { short[] ret = new short[num]; for (int i = 0; i < num; i++) @@ -321,6 +321,13 @@ namespace BizHawk return ret; } + public static ushort[] ReadUInt16s(this BinaryReader br, int num) + { + ushort[] ret = new ushort[num]; + for (int i = 0; i < num; i++) + ret[i] = br.ReadUInt16(); + return ret; + } public static void ReadFromHex(this byte[] buffer, string hex) { diff --git a/BizHawk.MultiClient/output/MusashiDLL.dll b/BizHawk.MultiClient/output/MusashiDLL.dll index 6068ce2f3a..bf15937a46 100644 Binary files a/BizHawk.MultiClient/output/MusashiDLL.dll and b/BizHawk.MultiClient/output/MusashiDLL.dll differ diff --git a/BizHawk.MultiClient/output/gamedb_pce_cd.txt b/BizHawk.MultiClient/output/gamedb_pce_cd.txt index 06fb96441d..0ee27d1858 100644 --- a/BizHawk.MultiClient/output/gamedb_pce_cd.txt +++ b/BizHawk.MultiClient/output/gamedb_pce_cd.txt @@ -94,8 +94,8 @@ CBA55D463FECF2955736AA2EA5D6BD74 Lodoss Tousenki - Record of Lodoss War PCE EFF6C174835503B034CF6A4079627DBD Road Spirits PCE FBC374F66ED4228120B74D327DE81298 B R-Type Complete CD (imperfect dump) PCE NeedSuperSysCard D71C2734BD4B048F810C80FE9BD4C6D0 R-Type Complete CD PCE NeedSuperSysCard -5D16FE7D452DC9B46CAA7A436F45468D Sapphire PCE NeedSuperSysCard;ArcadeCard -DFAC092A700697944CD741F657D94F17 Sapphire PCE NeedSuperSysCard;ArcadeCard +5D16FE7D452DC9B46CAA7A436F45468D Sapphire PCE NeedSuperSysCard;ArcadeCard;EqualizeVolumes +DFAC092A700697944CD741F657D94F17 Sapphire PCE NeedSuperSysCard;ArcadeCard;EqualizeVolumes D67A425615770ECE13CF5157CA32EF61 Shubibinman III PCE E6CB40FD1E315B84D09100915DCABF9C Shadow of the Beast (U) PCE NeedSuperSysCard;EqualizeVolumes C8559632FE3EA3B4FBABBEF80865B36C Shape Shifter (U) PCE NeedSuperSysCard