Much improved pce-cd savestateyfulness

Cleanup and stateyness of SCSI bus still in progress; states not done yet
This commit is contained in:
beirich 2011-09-16 04:59:59 +00:00
parent d529383826
commit 9aa70c4fa9
5 changed files with 212 additions and 80 deletions

View File

@ -76,6 +76,7 @@ namespace BizHawk.Emulation.CPUs.H6280
writer.Write("MPR ");
MPR.SaveAsHex(writer);
writer.WriteLine("IRQ1Assert {0}", IRQ1Assert);
writer.WriteLine("IRQ2Assert {0}", IRQ2Assert);
writer.WriteLine("TimerAssert {0}", TimerAssert);
writer.WriteLine("IRQControlByte {0:X2}", IRQControlByte);
writer.WriteLine("IRQNextControlByte {0:X2}", IRQNextControlByte);
@ -117,6 +118,8 @@ namespace BizHawk.Emulation.CPUs.H6280
MPR.ReadFromHex(args[1]);
else if (args[0] == "IRQ1Assert")
IRQ1Assert = bool.Parse(args[1]);
else if (args[0] == "IRQ2Assert")
IRQ2Assert = bool.Parse(args[1]);
else if (args[0] == "TimerAssert")
TimerAssert = bool.Parse(args[1]);
else if (args[0] == "IRQControlByte")
@ -162,6 +165,7 @@ namespace BizHawk.Emulation.CPUs.H6280
writer.Write(S);
writer.Write(MPR);
writer.Write(IRQ1Assert);
writer.Write(IRQ2Assert);
writer.Write(TimerAssert);
writer.Write(IRQControlByte);
writer.Write(IRQNextControlByte);
@ -191,6 +195,7 @@ namespace BizHawk.Emulation.CPUs.H6280
S = reader.ReadByte();
MPR = reader.ReadBytes(8);
IRQ1Assert = reader.ReadBoolean();
IRQ2Assert = reader.ReadBoolean();
TimerAssert = reader.ReadBoolean();
IRQControlByte = reader.ReadByte();
IRQNextControlByte = reader.ReadByte();

View File

@ -1,10 +1,18 @@
using System;
using BizHawk.Emulation.Sound;
using System.IO;
using System.Globalization;
namespace BizHawk.Emulation.Consoles.TurboGrafx
{
public sealed class ADPCM : ISoundProvider
{
ScsiCDBus SCSI;
PCEngine pce;
MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
// ***************************************************************************
public ushort IOAddress;
public ushort ReadAddress;
public ushort WriteAddress;
@ -15,11 +23,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public bool ReadPending, WritePending;
public byte[] RAM = new byte[0x10000];
ScsiCDBus SCSI;
PCEngine pce;
MetaspuSoundProvider SoundProvider = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
// ***************************************************************************
public bool AdpcmIsPlaying { get; private set; }
@ -29,21 +33,12 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public bool AdpcmBusyReading { get { return ReadPending; } }
public bool AdpcmCdDmaRequested { get { return (Port180B & 3) != 0; } }
// ***************************************************************************
public byte Port180A
{
set
{
WriteBuffer = value;
WriteTimer = 24;
WritePending = true;
}
get
{
ReadPending = true;
ReadTimer = 24;
return ReadBuffer;
}
set { WritePending = true; WriteTimer = 24; WriteBuffer = value; }
get { ReadPending = true; ReadTimer = 24; return ReadBuffer; }
}
public byte Port180B;
@ -58,7 +53,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
port180E = value;
float khz = 32 / (16 - (Port180E & 0x0F));
destSamplesPerSourceSample = 44.1f / khz;
}
}
@ -189,6 +183,13 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
// Playback Functions
// ***************************************************************************
float Playback44khzTimer;
int playingSample;
float nextSampleTimer;
float destSamplesPerSourceSample;
bool nibble;
int magnitude;
static readonly int[] StepSize =
{
0x0002, 0x0006, 0x000A, 0x000E, 0x0012, 0x0016, 0x001A, 0x001E,
@ -244,13 +245,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
static readonly int[] StepFactor = { -1, -1, -1, -1, 2, 4, 6, 8 };
float Playback44khzTimer;
int playingSample;
float nextSampleTimer = 0;
float destSamplesPerSourceSample;
bool nibble;
int magnitude;
int AddClamped(int num1, int num2, int min, int max)
{
int result = num1 + num2;
@ -325,5 +319,165 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
}
public int MaxVolume { get; set; }
// ***************************************************************************
public void SaveStateBinary(BinaryWriter writer)
{
writer.Write(RAM);
writer.Write(IOAddress);
writer.Write(AdpcmLength);
writer.Write(ReadAddress);
writer.Write((byte)ReadTimer);
writer.Write(ReadBuffer);
writer.Write(ReadPending);
writer.Write(WriteAddress);
writer.Write((byte)WriteTimer);
writer.Write(WriteBuffer);
writer.Write(WritePending);
writer.Write(Port180B);
writer.Write(Port180D);
writer.Write(Port180E);
writer.Write(AdpcmIsPlaying);
writer.Write(HalfReached);
writer.Write(EndReached);
writer.Write(Playback44khzTimer);
writer.Write((ushort)playingSample);
writer.Write(nextSampleTimer);
writer.Write(nibble);
writer.Write((byte)magnitude);
}
public void LoadStateBinary(BinaryReader reader)
{
RAM = reader.ReadBytes(0x10000);
IOAddress = reader.ReadUInt16();
AdpcmLength = reader.ReadUInt16();
ReadAddress = reader.ReadUInt16();
ReadTimer = reader.ReadByte();
ReadBuffer = reader.ReadByte();
ReadPending = reader.ReadBoolean();
WriteAddress = reader.ReadUInt16();
WriteTimer = reader.ReadByte();
WriteBuffer = reader.ReadByte();
WritePending = reader.ReadBoolean();
Port180B = reader.ReadByte();
Port180D = reader.ReadByte();
Port180E = reader.ReadByte();
AdpcmIsPlaying = reader.ReadBoolean();
HalfReached = reader.ReadBoolean();
EndReached = reader.ReadBoolean();
Playback44khzTimer = reader.ReadSingle();
playingSample = reader.ReadUInt16();
nextSampleTimer = reader.ReadSingle();
nibble = reader.ReadBoolean();
magnitude = reader.ReadByte();
pce.IntADPCM = HalfReached;
pce.IntStop = EndReached;
pce.RefreshIRQ2();
}
public void SaveStateText(TextWriter writer)
{
writer.WriteLine("[ADPCM]");
writer.Write("RAM ");
RAM.SaveAsHex(writer);
writer.WriteLine("IOAddress {0:X4}", IOAddress);
writer.WriteLine("AdpcmLength {0:X4}", AdpcmLength);
writer.WriteLine("ReadAddress {0:X4}", ReadAddress);
writer.WriteLine("ReadTimer {0}", ReadTimer);
writer.WriteLine("ReadBuffer {0:X2}", ReadBuffer);
writer.WriteLine("ReadPending {0}", ReadPending);
writer.WriteLine("WriteAddress {0:X4}", WriteAddress);
writer.WriteLine("WriteTimer {0}", WriteTimer);
writer.WriteLine("WriteBuffer {0:X2}", WriteBuffer);
writer.WriteLine("WritePending {0}", WritePending);
writer.WriteLine("Port180B {0:X2}", Port180B);
writer.WriteLine("Port180D {0:X2}", Port180D);
writer.WriteLine("Port180E {0:X2}", Port180E);
writer.WriteLine("AdpcmIsPlaying {0}", AdpcmIsPlaying);
writer.WriteLine("HalfReached {0}", HalfReached);
writer.WriteLine("EndReached {0}", EndReached);
writer.WriteLine("Playback44khzTimer {0}", Playback44khzTimer);
writer.WriteLine("PlayingSample {0:X4}", playingSample);
writer.WriteLine("NextSampleTimer {0}", nextSampleTimer);
writer.WriteLine("FirstNibble {0}", nibble);
writer.WriteLine("Magnitude {0}", magnitude);
writer.WriteLine("[/ADPCM]\n");
}
public void LoadStateText(TextReader reader)
{
while (true)
{
string[] args = reader.ReadLine().Split(' ');
if (args[0].Trim() == "") continue;
if (args[0] == "[/ADPCM]") break;
if (args[0] == "RAM")
RAM.ReadFromHex(args[1]);
else if (args[0] == "IOAddress")
IOAddress = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "AdpcmLength")
AdpcmLength = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "ReadAddress")
ReadAddress = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "ReadTimer")
ReadTimer = int.Parse(args[1]);
else if (args[0] == "ReadBuffer")
ReadBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "ReadPending")
ReadPending = bool.Parse(args[1]);
else if (args[0] == "WriteAddress")
WriteAddress = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "WriteTimer")
WriteTimer = int.Parse(args[1]);
else if (args[0] == "WriteBuffer")
WriteBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "WritePending")
WritePending = bool.Parse(args[1]);
else if (args[0] == "Port180B")
Port180B = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "Port180D")
Port180D = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "Port180E")
Port180E = byte.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "AdpcmIsPlaying")
AdpcmIsPlaying = bool.Parse(args[1]);
else if (args[0] == "HalfReached")
HalfReached = bool.Parse(args[1]);
else if (args[0] == "EndReached")
EndReached = bool.Parse(args[1]);
else if (args[0] == "Playback44khzTimer")
Playback44khzTimer = float.Parse(args[1]);
else if (args[0] == "PlayingSample")
playingSample = ushort.Parse(args[1], NumberStyles.HexNumber);
else if (args[0] == "NextSampleTimer")
nextSampleTimer = float.Parse(args[1]);
else if (args[0] == "FirstNibble")
nibble = bool.Parse(args[1]);
else if (args[0] == "Magnitude")
magnitude = int.Parse(args[1]);
else
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
}
pce.IntADPCM = HalfReached;
pce.IntStop = EndReached;
pce.RefreshIRQ2();
}
}
}
}

View File

@ -264,6 +264,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public bool SaveRamModified { get; set; }
// TODO: properly savestate SCSI
public void SaveStateText(TextWriter writer)
{
writer.WriteLine("[PCEngine]");
@ -274,8 +276,8 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.Write("PopulousRAM ");
PopulousRAM.SaveAsHex(writer);
}
writer.WriteLine("Frame " + Frame);
writer.WriteLine("Lag " + _lagcount);
writer.WriteLine("Frame {0}", Frame);
writer.WriteLine("Lag {0}", _lagcount);
if (Cpu.ReadMemory21 == ReadMemorySF2)
writer.WriteLine("SF2MapperLatch " + SF2MapperLatch);
writer.WriteLine("IOBuffer {0:X2}", IOBuffer);
@ -307,8 +309,9 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
writer.Write("SuperRAM ");
SuperRam.SaveAsHex(writer);
}
writer.Write("ADPCM_TEMP ");
ADPCM.RAM.SaveAsHex(writer);
writer.WriteLine();
ADPCM.SaveStateText(writer);
}
writer.WriteLine("[/PCEngine]");
}
@ -335,8 +338,6 @@ ADPCM.RAM.SaveAsHex(writer);
CDRam.ReadFromHex(args[1]);
else if (args[0] == "SuperRAM")
SuperRam.ReadFromHex(args[1]);
else if (args[0] == "ADPCM_TEMP")
ADPCM.RAM.ReadFromHex(args[1]);
else if (args[0] == "PopulousRAM" && PopulousRAM != null)
PopulousRAM.ReadFromHex(args[1]);
else if (args[0] == "[HuC6280]")
@ -353,6 +354,8 @@ ADPCM.RAM.ReadFromHex(args[1]);
VDC2.LoadStateText(reader, 2);
else if (args[0] == "[CDAudio]")
CDAudio.LoadStateText(reader);
else if (args[0] == "[ADPCM]")
ADPCM.LoadStateText(reader);
else
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
}
@ -363,6 +366,8 @@ ADPCM.RAM.ReadFromHex(args[1]);
if (SuperGrafx == false)
{
writer.Write(Ram);
writer.Write(CdIoPorts);
RefreshIRQ2();
if (BRAM != null)
writer.Write(BRAM);
if (PopulousRAM != null)
@ -372,7 +377,7 @@ ADPCM.RAM.ReadFromHex(args[1]);
if (TurboCD)
{
writer.Write(CDRam);
writer.Write(ADPCM.RAM);
ADPCM.SaveStateBinary(writer);
}
writer.Write(Frame);
writer.Write(_lagcount);
@ -405,6 +410,7 @@ ADPCM.RAM.ReadFromHex(args[1]);
if (SuperGrafx == false)
{
Ram = reader.ReadBytes(0x2000);
CdIoPorts = reader.ReadBytes(16);
if (BRAM != null)
BRAM = reader.ReadBytes(0x800);
if (PopulousRAM != null)
@ -414,7 +420,7 @@ ADPCM.RAM.ReadFromHex(args[1]);
if (TurboCD)
{
CDRam = reader.ReadBytes(0x10000);
ADPCM.RAM = reader.ReadBytes(0x10000);
ADPCM.LoadStateBinary(reader);
}
Frame = reader.ReadInt32();
_lagcount = reader.ReadInt32();
@ -444,12 +450,12 @@ ADPCM.RAM.ReadFromHex(args[1]);
public byte[] SaveStateBinary()
{
int buflen = 75870;
int buflen = 75887;
if (SuperGrafx) buflen += 90698;
if (BramEnabled) buflen += 2048;
if (PopulousRAM != null) buflen += 0x8000;
if (SuperRam != null) buflen += 0x30000;
if (TurboCD) buflen += 0x20000 + 30;
if (TurboCD) buflen += 0x20000 + 62;
//Console.WriteLine("LENGTH1 " + buflen);
var buf = new byte[buflen];

View File

@ -6,9 +6,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
{
public static byte[] CdIoPorts = new byte[16];
public byte IRQ2Control { get { return CdIoPorts[2]; } set { CdIoPorts[2] = value; } }
public byte IRQ2Monitor { get { return CdIoPorts[3]; } set { CdIoPorts[3] = value; } }
public bool IntADPCM // INTA
{
get { return (CdIoPorts[3] & 0x04) != 0; }
@ -35,17 +32,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
set { CdIoPorts[3] = (byte)((CdIoPorts[3] & ~0x40) | (value ? 0x40 : 0x00)); }
}
public byte Port1803
{
get { return CdIoPorts[3]; }
set
{
if (value != CdIoPorts[3])
Console.WriteLine("UPDATE 1803: From {0:X2} to {1:X2}", CdIoPorts[3], value);
CdIoPorts[3] = value;
}
}
void SetCDAudioCallback()
{
CDAudio.CallbackAction = () =>
@ -58,27 +44,21 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
void WriteCD(int addr, byte value)
{
//Log.Error("CD","Write: {0:X4} {1:X2} (PC={2:X4})", addr & 0x1FFF, value, Cpu.PC);
switch (addr & 0x1FFF)
{
case 0x1800: // SCSI Drive Control Line
CdIoPorts[0] = value;
// Console.WriteLine("Write to CDC Status [0] {0:X2}", value);
SCSI.SEL = true;
SCSI.Think();
SCSI.SEL = false;
SCSI.Think();
// this probably does some things
// possibly clear irq line or trigger or who knows
break;
case 0x1801: // CDC Command
CdIoPorts[1] = value;
SCSI.DataBits = value;
SCSI.Think();
// Console.WriteLine("Write to CDC Command [1] {0:X2}", value);
break;
case 0x1802: // ACK and Interrupt Control
@ -103,7 +83,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
SCSI.Think();
if (SCSI.RST)
{
Port1803 &= 0x8F; // Clear interrupt control bits
CdIoPorts[3] &= 0x8F; // Clear interrupt control bits
RefreshIRQ2();
}
break;
@ -126,7 +106,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Console.WriteLine("doing silly thing");
ADPCM.AdpcmLength = ADPCM.IOAddress;
}
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
break;
case 0x1809: // ADPCM address MSB
@ -137,7 +116,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
Console.WriteLine("doing silly thing");
ADPCM.AdpcmLength = ADPCM.IOAddress;
}
//Log.Error("CD", "adpcm address = {0:X4}", ADPCM.adpcm_io_address);
break;
case 0x180A: // ADPCM Memory Read/Write Port
@ -146,7 +124,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x180B: // ADPCM DMA Control
ADPCM.Port180B = value;
//Log.Error("CD", "Write to ADPCM DMA Control [B] {0:X2}", value);
if (ADPCM.AdpcmCdDmaRequested)
Console.WriteLine(" ADPCM DMA REQUESTED");
break;
@ -157,14 +134,11 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
case 0x180E: // ADPCM Playback Rate
ADPCM.Port180E = value;
//Log.Error("CD", "Write to ADPCM Sample Rate [E] {0:X2}", value);
break;
case 0x180F: // Audio Fade Timer
CdIoPorts[0x0F] = value;
//Log.Error("CD", "Write to CD Audio fade timer [F] {0:X2}", value);
// TODO ADPCM fades/vol control also.
switch (value)
{
case 0:
@ -204,46 +178,39 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
if (SCSI.MSG) returnValue |= 0x20;
if (SCSI.REQ) returnValue |= 0x40;
if (SCSI.BSY) returnValue |= 0x80;
//Log.Error("CD", "Read: 1800 {0:X2} (PC={1:X4})", returnValue, Cpu.PC);
return returnValue;
case 0x1801: // Read data bus
//Log.Error("CD", "Read: 1801 {0:X2} (PC={1:X4})", SCSI.DataBits, Cpu.PC);
return SCSI.DataBits;
case 0x1802: // ADPCM / CD Control
//Log.Error("CD", "Read: 1802 {0:X2} (PC={1:X4})", CdIoPorts[2], Cpu.PC);
return CdIoPorts[2];
case 0x1803: // BRAM Lock
if (BramEnabled)
BramLocked = true;
//Log.Error("CD", "Read: 1803 {0:X2} (PC={1:X4})", CdIoPorts[3], Cpu.PC);
returnValue = Port1803;
returnValue = CdIoPorts[3];
CdIoPorts[3] ^= 2;
return returnValue;
case 0x1804: // CD Reset
//Log.Error("CD", "Read: 1804 {0:X2} (PC={1:X4})", CdIoPorts[4], Cpu.PC);
return CdIoPorts[4];
case 0x1805: // CD audio data Low
if ((Port1803 & 0x2) == 0)
if ((CdIoPorts[3] & 0x2) == 0)
sample = CDAudio.VolumeLeft;
else
sample = CDAudio.VolumeRight;
return (byte) sample;
case 0x1806: // CD audio data High
if ((Port1803 & 0x2) == 0)
if ((CdIoPorts[3] & 0x2) == 0)
sample = CDAudio.VolumeLeft;
else
sample = CDAudio.VolumeRight;
return (byte) (sample >> 8);
// wow, nothing ever reads 1807 yet
case 0x1808: // Auto Handshake Data Input
returnValue = SCSI.DataBits;
if (SCSI.REQ && SCSI.IO && !SCSI.CD)
@ -258,7 +225,6 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
return ADPCM.Port180A;
case 0x180B: // ADPCM Data Transfer Control
//Log.Error("CD", "Read ADPCM Data Transfer Control");
return ADPCM.Port180B;
case 0x180C: // ADPCM Status
@ -271,17 +237,14 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
returnValue |= 0x04;
if (ADPCM.AdpcmBusyReading)
returnValue |= 0x80;
//Log.Error("CD", "Read ADPCM Status {0:X2}", returnValue);
return returnValue;
case 0x180D: // ADPCM Play Control
//Log.Error("CD", "Read ADPCM Play Control");
return CdIoPorts[0x0D];
case 0x180F: // Audio Fade Timer
//Log.Error("CD", "Read: 180F {0:X2} (PC={1:X4})", CdIoPorts[0xF], Cpu.PC);
return CdIoPorts[0x0F];
// These are some retarded version check
@ -300,7 +263,7 @@ namespace BizHawk.Emulation.Consoles.TurboGrafx
public void RefreshIRQ2()
{
int mask = CdIoPorts[2] & Port1803 & 0x7C;
int mask = CdIoPorts[2] & CdIoPorts[3] & 0x7C;
Cpu.IRQ2Assert = (mask != 0);
}
}

View File

@ -261,6 +261,10 @@ namespace BizHawk.Emulation.Sound
CurrentSector = int.Parse(args[1]);
else if (args[0] == "SectorOffset")
SectorOffset = int.Parse(args[1]);
else if (args[0] == "FadeOutOverFrames")
FadeOutOverFrames = int.Parse(args[1]);
else if (args[0] == "FadeOutFramesRemaining")
FadeOutFramesRemaining = int.Parse(args[1]);
else
Console.WriteLine("Skipping unrecognized identifier " + args[0]);