fix Disc/Disc name collision
add function to disc-api to get game-ID hash from 1st data track
This commit is contained in:
parent
adc0bf83bb
commit
74a58186df
|
@ -4,382 +4,378 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using BizHawk.Emulation.CPUs.H6280;
|
using BizHawk.Emulation.CPUs.H6280;
|
||||||
using BizHawk.Emulation.Sound;
|
using BizHawk.Emulation.Sound;
|
||||||
using BizHawk.Disc;
|
using BizHawk.DiscSystem;
|
||||||
|
|
||||||
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
namespace BizHawk.Emulation.Consoles.TurboGrafx
|
||||||
{
|
{
|
||||||
public enum NecSystemType
|
public enum NecSystemType
|
||||||
{
|
{
|
||||||
TurboGrafx,
|
TurboGrafx,
|
||||||
TurboCD,
|
TurboCD,
|
||||||
SuperGrafx
|
SuperGrafx
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed partial class PCEngine : IEmulator
|
public sealed partial class PCEngine : IEmulator
|
||||||
{
|
{
|
||||||
// ROM
|
// ROM
|
||||||
public byte[] RomData;
|
public byte[] RomData;
|
||||||
public int RomLength;
|
public int RomLength;
|
||||||
|
|
||||||
// Machine
|
// Machine
|
||||||
public NecSystemType Type;
|
public NecSystemType Type;
|
||||||
public HuC6280 Cpu;
|
public HuC6280 Cpu;
|
||||||
public VDC VDC1, VDC2;
|
public VDC VDC1, VDC2;
|
||||||
public VCE VCE;
|
public VCE VCE;
|
||||||
public HuC6280PSG PSG;
|
public HuC6280PSG PSG;
|
||||||
public VPC VPC;
|
public VPC VPC;
|
||||||
|
|
||||||
private bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
|
private bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
|
||||||
private bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
|
private bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
|
||||||
private bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
|
private bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
|
||||||
|
|
||||||
|
// BRAM
|
||||||
|
private bool BramEnabled = false;
|
||||||
|
private bool BramLocked = true;
|
||||||
|
private byte[] BRAM;
|
||||||
|
|
||||||
// BRAM
|
// Memory system
|
||||||
private bool BramEnabled = false;
|
public byte[] Ram;
|
||||||
private bool BramLocked = true;
|
|
||||||
private byte[] BRAM;
|
|
||||||
|
|
||||||
// Memory system
|
// Disc
|
||||||
public byte[] Ram;
|
//private Disc disc = Disc.FromCuePath("D:/lib/roms/Turbo CD/Terra Forming/Syd Mead's Terra Forming [U][CD.SCD][TGXCD1040][Syd Mead][1993][PCE][rigg].cue");
|
||||||
|
|
||||||
// Disc
|
// PC Engine timings:
|
||||||
//private Disc.Disc disc = Disc.Disc.FromCuePath("d:/lib/roms/Turbo CD/Cosmic Fantasy II/Cosmic Fantasy II [U][CD][WTG990301][Telenet Japan][1992][PCE][thx-1138-darkwater].cue");
|
// 21,477,270 Machine clocks / sec
|
||||||
|
// 7,159,090 Cpu cycles / sec
|
||||||
|
|
||||||
// PC Engine timings:
|
public PCEngine(NecSystemType type)
|
||||||
// 21,477,270 Machine clocks / sec
|
{
|
||||||
// 7,159,090 Cpu cycles / sec
|
//scsi.disc = disc;
|
||||||
|
//Console.WriteLine(disc.GetHash());
|
||||||
|
CoreOutputComm = new CoreOutputComm();
|
||||||
|
Type = type;
|
||||||
|
Controller = NullController.GetNullController();
|
||||||
|
Cpu = new HuC6280();
|
||||||
|
VCE = new VCE();
|
||||||
|
VDC1 = new VDC(Cpu, VCE);
|
||||||
|
PSG = new HuC6280PSG();
|
||||||
|
|
||||||
public PCEngine(NecSystemType type)
|
if (TurboGrafx || TurboCD)
|
||||||
{
|
{
|
||||||
CoreOutputComm = new CoreOutputComm();
|
Ram = new byte[0x2000];
|
||||||
Type = type;
|
Cpu.ReadMemory21 = ReadMemory;
|
||||||
Controller = NullController.GetNullController();
|
Cpu.WriteMemory21 = WriteMemory;
|
||||||
Cpu = new HuC6280();
|
Cpu.WriteVDC = VDC1.WriteVDC;
|
||||||
VCE = new VCE();
|
}
|
||||||
VDC1 = new VDC(Cpu, VCE);
|
|
||||||
PSG = new HuC6280PSG();
|
|
||||||
|
|
||||||
if (TurboGrafx || TurboCD)
|
if (SuperGrafx)
|
||||||
{
|
{
|
||||||
Ram = new byte[0x2000];
|
VDC2 = new VDC(Cpu, VCE);
|
||||||
Cpu.ReadMemory21 = ReadMemory;
|
VPC = new VPC(VDC1, VDC2, VCE, Cpu);
|
||||||
Cpu.WriteMemory21 = WriteMemory;
|
Ram = new byte[0x8000];
|
||||||
Cpu.WriteVDC = VDC1.WriteVDC;
|
Cpu.ReadMemory21 = ReadMemorySGX;
|
||||||
}
|
Cpu.WriteMemory21 = WriteMemorySGX;
|
||||||
|
Cpu.WriteVDC = VDC1.WriteVDC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SuperGrafx)
|
public void LoadGame(IGame game)
|
||||||
{
|
{
|
||||||
VDC2 = new VDC(Cpu, VCE);
|
if (game.GetRomData().Length == 0x60000)
|
||||||
VPC = new VPC(VDC1, VDC2, VCE, Cpu);
|
{
|
||||||
Ram = new byte[0x8000];
|
// 384k roms require special loading code. Why ;_;
|
||||||
Cpu.ReadMemory21 = ReadMemorySGX;
|
// In memory, 384k roms look like [1st 256k][Then full 384k]
|
||||||
Cpu.WriteMemory21 = WriteMemorySGX;
|
RomData = new byte[0xA0000];
|
||||||
Cpu.WriteVDC = VDC1.WriteVDC;
|
var origRom = game.GetRomData();
|
||||||
}
|
for (int i=0; i<0x40000; i++)
|
||||||
}
|
RomData[i] = origRom[i];
|
||||||
|
for (int i = 0; i < 0x60000; i++)
|
||||||
|
RomData[i+0x40000] = origRom[i];
|
||||||
|
RomLength = RomData.Length;
|
||||||
|
} else if (game.GetRomData().Length > 1024 * 1024) {
|
||||||
|
// If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper
|
||||||
|
Cpu.ReadMemory21 = ReadMemorySF2;
|
||||||
|
Cpu.WriteMemory21 = WriteMemorySF2;
|
||||||
|
RomData = game.GetRomData();
|
||||||
|
RomLength = RomData.Length;
|
||||||
|
} else {
|
||||||
|
// normal rom.
|
||||||
|
RomData = game.GetRomData();
|
||||||
|
RomLength = RomData.Length;
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadGame(IGame game)
|
if (game.GetOptions().Contains("BRAM"))
|
||||||
{
|
{
|
||||||
if (game.GetRomData().Length == 0x60000)
|
BramEnabled = true;
|
||||||
{
|
BRAM = new byte[2048];
|
||||||
// 384k roms require special loading code. Why ;_;
|
Console.WriteLine("ENABLE BRAM!");
|
||||||
// In memory, 384k roms look like [1st 256k][Then full 384k]
|
|
||||||
RomData = new byte[0xA0000];
|
|
||||||
var origRom = game.GetRomData();
|
|
||||||
for (int i = 0; i < 0x40000; i++)
|
|
||||||
RomData[i] = origRom[i];
|
|
||||||
for (int i = 0; i < 0x60000; i++)
|
|
||||||
RomData[i + 0x40000] = origRom[i];
|
|
||||||
RomLength = RomData.Length;
|
|
||||||
}
|
|
||||||
else if (game.GetRomData().Length > 1024 * 1024)
|
|
||||||
{
|
|
||||||
// If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper
|
|
||||||
Cpu.ReadMemory21 = ReadMemorySF2;
|
|
||||||
Cpu.WriteMemory21 = WriteMemorySF2;
|
|
||||||
RomData = game.GetRomData();
|
|
||||||
RomLength = RomData.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// normal rom.
|
|
||||||
RomData = game.GetRomData();
|
|
||||||
RomLength = RomData.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game.GetOptions().Contains("BRAM"))
|
// pre-format BRAM
|
||||||
{
|
BRAM[0] = 0x48; BRAM[1] = 0x55; BRAM[2] = 0x42; BRAM[3] = 0x4D;
|
||||||
BramEnabled = true;
|
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
|
||||||
BRAM = new byte[2048];
|
}
|
||||||
Console.WriteLine("ENABLE BRAM!");
|
|
||||||
|
|
||||||
// pre-format BRAM
|
if (game.GetOptions().Contains("PopulousSRAM"))
|
||||||
BRAM[0] = 0x48; BRAM[1] = 0x55; BRAM[2] = 0x42; BRAM[3] = 0x4D;
|
{
|
||||||
BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80;
|
PopulousRAM = new byte[0x8000];
|
||||||
}
|
Cpu.ReadMemory21 = ReadMemoryPopulous;
|
||||||
|
Cpu.WriteMemory21 = WriteMemoryPopulous;
|
||||||
|
}
|
||||||
|
|
||||||
if (game.GetOptions().Contains("PopulousSRAM"))
|
if (game.GetOptions().Contains("ForceSpriteLimit") || game.GetOptions().Contains("NotInDatabase"))
|
||||||
{
|
{
|
||||||
PopulousRAM = new byte[0x8000];
|
VDC1.PerformSpriteLimit = true;
|
||||||
Cpu.ReadMemory21 = ReadMemoryPopulous;
|
if (VDC2 != null)
|
||||||
Cpu.WriteMemory21 = WriteMemoryPopulous;
|
VDC2.PerformSpriteLimit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.GetOptions().Contains("ForceSpriteLimit") || game.GetOptions().Contains("NotInDatabase"))
|
// Ok, yes, HBlankPeriod's only purpose is game-specific hax.
|
||||||
{
|
// 1) At least they're not coded directly into the emulator, but instead data-driven.
|
||||||
VDC1.PerformSpriteLimit = true;
|
// 2) The games which have custom HBlankPeriods work without it, the override only
|
||||||
if (VDC2 != null)
|
// serves to clean up minor gfx anomalies.
|
||||||
VDC2.PerformSpriteLimit = true;
|
// 3) There's no point in haxing the timing with incorrect values in an attempt to avoid this.
|
||||||
}
|
// The proper fix is cycle-accurate/bus-accurate timing. That isn't coming to the C#
|
||||||
|
// version of this core. Let's just acknolwedge that the timing is imperfect and fix
|
||||||
|
// it in the least intrusive and most honest way we can.
|
||||||
|
|
||||||
// Ok, yes, HBlankPeriod's only purpose is game-specific hax.
|
if (game.GetOptions().ContainsStartsWith("HBlankPeriod"))
|
||||||
// 1) At least they're not coded directly into the emulator, but instead data-driven.
|
VDC1.HBlankCycles = int.Parse(game.GetOptions().GetOptionValue("HBlankPeriod"));
|
||||||
// 2) The games which have custom HBlankPeriods work without it, the override only
|
|
||||||
// serves to clean up minor gfx anomalies.
|
|
||||||
// 3) There's no point in haxing the timing with incorrect values in an attempt to avoid this.
|
|
||||||
// The proper fix is cycle-accurate/bus-accurate timing. That isn't coming to the C#
|
|
||||||
// version of this core. Let's just acknolwedge that the timing is imperfect and fix
|
|
||||||
// it in the least intrusive and most honest way we can.
|
|
||||||
|
|
||||||
if (game.GetOptions().ContainsStartsWith("HBlankPeriod"))
|
// This is also a hack. Proper multi-res/TV emulation will be a native-code core feature.
|
||||||
VDC1.HBlankCycles = int.Parse(game.GetOptions().GetOptionValue("HBlankPeriod"));
|
|
||||||
|
if (game.GetOptions().ContainsStartsWith("MultiResHack"))
|
||||||
|
{
|
||||||
|
VDC1.MultiResHack = int.Parse(game.GetOptions().GetOptionValue("MultiResHack"));
|
||||||
|
}
|
||||||
|
|
||||||
// This is also a hack. Proper multi-res/TV emulation will be a native-code core feature.
|
Cpu.ResetPC();
|
||||||
|
SetupMemoryDomains();
|
||||||
|
}
|
||||||
|
|
||||||
if (game.GetOptions().ContainsStartsWith("MultiResHack"))
|
private int _lagcount = 0;
|
||||||
{
|
private bool lagged = true;
|
||||||
VDC1.MultiResHack = int.Parse(game.GetOptions().GetOptionValue("MultiResHack"));
|
private bool islag = false;
|
||||||
}
|
public int Frame { get; set; }
|
||||||
|
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||||
|
public bool IsLagFrame { get { return islag; } }
|
||||||
|
|
||||||
Cpu.ResetPC();
|
public void ResetFrameCounter()
|
||||||
SetupMemoryDomains();
|
{
|
||||||
}
|
// this should just be a public setter instead of a new method.
|
||||||
|
Frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int _lagcount = 0;
|
public void FrameAdvance(bool render)
|
||||||
private bool lagged = true;
|
{
|
||||||
private bool islag = false;
|
lagged = true;
|
||||||
public int Frame { get; set; }
|
Controller.UpdateControls(Frame++);
|
||||||
public void ResetFrameCounter()
|
|
||||||
{
|
|
||||||
Frame = 0;
|
|
||||||
}
|
|
||||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
|
||||||
public bool IsLagFrame { get { return islag; } }
|
|
||||||
|
|
||||||
public void FrameAdvance(bool render)
|
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
||||||
{
|
|
||||||
lagged = true;
|
|
||||||
Controller.UpdateControls(Frame++);
|
|
||||||
|
|
||||||
PSG.BeginFrame(Cpu.TotalExecutedCycles);
|
if (SuperGrafx)
|
||||||
|
VPC.ExecFrame(render);
|
||||||
|
else
|
||||||
|
VDC1.ExecFrame(render);
|
||||||
|
|
||||||
if (SuperGrafx)
|
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
||||||
VPC.ExecFrame(render);
|
if (lagged)
|
||||||
else
|
{
|
||||||
VDC1.ExecFrame(render);
|
_lagcount++;
|
||||||
|
islag = true;
|
||||||
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
}
|
||||||
if (lagged)
|
else
|
||||||
{
|
islag = false;
|
||||||
_lagcount++;
|
}
|
||||||
islag = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
islag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CoreInputComm CoreInputComm { get; set; }
|
public CoreInputComm CoreInputComm { get; set; }
|
||||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||||
|
|
||||||
public IVideoProvider VideoProvider
|
public IVideoProvider VideoProvider
|
||||||
{
|
{
|
||||||
get { return (IVideoProvider)VPC ?? VDC1; }
|
get { return (IVideoProvider) VPC ?? VDC1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISoundProvider SoundProvider
|
public ISoundProvider SoundProvider
|
||||||
{
|
{
|
||||||
get { return PSG; }
|
get { return PSG; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SystemId { get { return "PCE"; } }
|
||||||
|
public string Region { get; set; }
|
||||||
|
public bool DeterministicEmulation { get; set; }
|
||||||
|
|
||||||
public string SystemId { get { return "PCE"; } }
|
public byte[] SaveRam
|
||||||
public string Region { get; set; }
|
{
|
||||||
public bool DeterministicEmulation { get; set; }
|
get { return BRAM; }
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] SaveRam
|
public bool SaveRamModified { get; set; }
|
||||||
{
|
|
||||||
get { return BRAM; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SaveRamModified { get; set; }
|
public void SaveStateText(TextWriter writer)
|
||||||
|
{
|
||||||
|
writer.WriteLine("[PCEngine]");
|
||||||
|
writer.Write("RAM ");
|
||||||
|
Ram.SaveAsHex(writer);
|
||||||
|
if (PopulousRAM != null)
|
||||||
|
{
|
||||||
|
writer.Write("PopulousRAM ");
|
||||||
|
PopulousRAM.SaveAsHex(writer);
|
||||||
|
}
|
||||||
|
writer.WriteLine("Frame " + Frame);
|
||||||
|
writer.WriteLine("Lag " + _lagcount);
|
||||||
|
if (Cpu.ReadMemory21 == ReadMemorySF2)
|
||||||
|
writer.WriteLine("SF2MapperLatch " + SF2MapperLatch);
|
||||||
|
writer.WriteLine("IOBuffer {0:X2}", IOBuffer);
|
||||||
|
writer.WriteLine();
|
||||||
|
|
||||||
public void SaveStateText(TextWriter writer)
|
if (SuperGrafx)
|
||||||
{
|
{
|
||||||
writer.WriteLine("[PCEngine]");
|
Cpu.SaveStateText(writer);
|
||||||
writer.Write("RAM ");
|
VPC.SaveStateText(writer);
|
||||||
Ram.SaveAsHex(writer);
|
VCE.SaveStateText(writer);
|
||||||
if (PopulousRAM != null)
|
VDC1.SaveStateText(writer, 1);
|
||||||
{
|
VDC2.SaveStateText(writer, 2);
|
||||||
writer.Write("PopulousRAM ");
|
PSG.SaveStateText(writer);
|
||||||
PopulousRAM.SaveAsHex(writer);
|
}
|
||||||
}
|
else
|
||||||
writer.WriteLine("Frame " + Frame);
|
{
|
||||||
writer.WriteLine("Lag " + _lagcount);
|
Cpu.SaveStateText(writer);
|
||||||
if (Cpu.ReadMemory21 == ReadMemorySF2)
|
VCE.SaveStateText(writer);
|
||||||
writer.WriteLine("SF2MapperLatch " + SF2MapperLatch);
|
VDC1.SaveStateText(writer, 1);
|
||||||
writer.WriteLine("IOBuffer {0:X2}", IOBuffer);
|
PSG.SaveStateText(writer);
|
||||||
writer.WriteLine();
|
}
|
||||||
|
writer.WriteLine("[/PCEngine]");
|
||||||
|
}
|
||||||
|
|
||||||
if (SuperGrafx)
|
public void LoadStateText(TextReader reader)
|
||||||
{
|
{
|
||||||
Cpu.SaveStateText(writer);
|
while (true)
|
||||||
VPC.SaveStateText(writer);
|
{
|
||||||
VCE.SaveStateText(writer);
|
string[] args = reader.ReadLine().Split(' ');
|
||||||
VDC1.SaveStateText(writer, 1);
|
if (args[0].Trim() == "") continue;
|
||||||
VDC2.SaveStateText(writer, 2);
|
if (args[0] == "[PCEngine]") continue;
|
||||||
PSG.SaveStateText(writer);
|
if (args[0] == "[/PCEngine]") break;
|
||||||
}
|
if (args[0] == "Frame")
|
||||||
else
|
Frame = int.Parse(args[1]);
|
||||||
{
|
else if (args[0] == "Lag")
|
||||||
Cpu.SaveStateText(writer);
|
_lagcount = int.Parse(args[1]);
|
||||||
VCE.SaveStateText(writer);
|
else if (args[0] == "SF2MapperLatch")
|
||||||
VDC1.SaveStateText(writer, 1);
|
SF2MapperLatch = byte.Parse(args[1]);
|
||||||
PSG.SaveStateText(writer);
|
else if (args[0] == "IOBuffer")
|
||||||
}
|
IOBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
|
||||||
writer.WriteLine("[/PCEngine]");
|
else if (args[0] == "RAM")
|
||||||
}
|
Ram.ReadFromHex(args[1]);
|
||||||
|
else if (args[0] == "PopulousRAM" && PopulousRAM != null)
|
||||||
|
PopulousRAM.ReadFromHex(args[1]);
|
||||||
|
else if (args[0] == "[HuC6280]")
|
||||||
|
Cpu.LoadStateText(reader);
|
||||||
|
else if (args[0] == "[PSG]")
|
||||||
|
PSG.LoadStateText(reader);
|
||||||
|
else if (args[0] == "[VCE]")
|
||||||
|
VCE.LoadStateText(reader);
|
||||||
|
else if (args[0] == "[VPC]")
|
||||||
|
VPC.LoadStateText(reader);
|
||||||
|
else if (args[0] == "[VDC1]")
|
||||||
|
VDC1.LoadStateText(reader, 1);
|
||||||
|
else if (args[0] == "[VDC2]")
|
||||||
|
VDC2.LoadStateText(reader, 2);
|
||||||
|
else
|
||||||
|
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadStateText(TextReader reader)
|
public void SaveStateBinary(BinaryWriter writer)
|
||||||
{
|
{
|
||||||
while (true)
|
if (SuperGrafx == false)
|
||||||
{
|
{
|
||||||
string[] args = reader.ReadLine().Split(' ');
|
writer.Write(Ram);
|
||||||
if (args[0].Trim() == "") continue;
|
if (PopulousRAM != null)
|
||||||
if (args[0] == "[PCEngine]") continue;
|
writer.Write(PopulousRAM);
|
||||||
if (args[0] == "[/PCEngine]") break;
|
writer.Write(Frame);
|
||||||
if (args[0] == "Frame")
|
writer.Write(_lagcount);
|
||||||
Frame = int.Parse(args[1]);
|
writer.Write(SF2MapperLatch);
|
||||||
else if (args[0] == "Lag")
|
writer.Write(IOBuffer);
|
||||||
_lagcount = int.Parse(args[1]);
|
Cpu.SaveStateBinary(writer);
|
||||||
else if (args[0] == "SF2MapperLatch")
|
VCE.SaveStateBinary(writer);
|
||||||
SF2MapperLatch = byte.Parse(args[1]);
|
VDC1.SaveStateBinary(writer);
|
||||||
else if (args[0] == "IOBuffer")
|
PSG.SaveStateBinary(writer);
|
||||||
IOBuffer = byte.Parse(args[1], NumberStyles.HexNumber);
|
} else {
|
||||||
else if (args[0] == "RAM")
|
writer.Write(Ram);
|
||||||
Ram.ReadFromHex(args[1]);
|
writer.Write(Frame);
|
||||||
else if (args[0] == "PopulousRAM" && PopulousRAM != null)
|
writer.Write(_lagcount);
|
||||||
PopulousRAM.ReadFromHex(args[1]);
|
writer.Write(IOBuffer);
|
||||||
else if (args[0] == "[HuC6280]")
|
Cpu.SaveStateBinary(writer);
|
||||||
Cpu.LoadStateText(reader);
|
VCE.SaveStateBinary(writer);
|
||||||
else if (args[0] == "[PSG]")
|
VPC.SaveStateBinary(writer);
|
||||||
PSG.LoadStateText(reader);
|
VDC1.SaveStateBinary(writer);
|
||||||
else if (args[0] == "[VCE]")
|
VDC2.SaveStateBinary(writer);
|
||||||
VCE.LoadStateText(reader);
|
PSG.SaveStateBinary(writer);
|
||||||
else if (args[0] == "[VPC]")
|
}
|
||||||
VPC.LoadStateText(reader);
|
}
|
||||||
else if (args[0] == "[VDC1]")
|
|
||||||
VDC1.LoadStateText(reader, 1);
|
|
||||||
else if (args[0] == "[VDC2]")
|
|
||||||
VDC2.LoadStateText(reader, 2);
|
|
||||||
else
|
|
||||||
Console.WriteLine("Skipping unrecognized identifier " + args[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveStateBinary(BinaryWriter writer)
|
public void LoadStateBinary(BinaryReader reader)
|
||||||
{
|
{
|
||||||
if (SuperGrafx == false)
|
if (SuperGrafx == false)
|
||||||
{
|
{
|
||||||
writer.Write(Ram);
|
Ram = reader.ReadBytes(0x2000);
|
||||||
if (PopulousRAM != null)
|
if (PopulousRAM != null)
|
||||||
writer.Write(PopulousRAM);
|
PopulousRAM = reader.ReadBytes(0x8000);
|
||||||
writer.Write(Frame);
|
Frame = reader.ReadInt32();
|
||||||
writer.Write(_lagcount);
|
_lagcount = reader.ReadInt32();
|
||||||
writer.Write(SF2MapperLatch);
|
SF2MapperLatch = reader.ReadByte();
|
||||||
writer.Write(IOBuffer);
|
IOBuffer = reader.ReadByte();
|
||||||
Cpu.SaveStateBinary(writer);
|
Cpu.LoadStateBinary(reader);
|
||||||
VCE.SaveStateBinary(writer);
|
VCE.LoadStateBinary(reader);
|
||||||
VDC1.SaveStateBinary(writer);
|
VDC1.LoadStateBinary(reader);
|
||||||
PSG.SaveStateBinary(writer);
|
PSG.LoadStateBinary(reader);
|
||||||
}
|
} else {
|
||||||
else
|
Ram = reader.ReadBytes(0x8000);
|
||||||
{
|
Frame = reader.ReadInt32();
|
||||||
writer.Write(Ram);
|
_lagcount = reader.ReadInt32();
|
||||||
writer.Write(Frame);
|
IOBuffer = reader.ReadByte();
|
||||||
writer.Write(_lagcount);
|
Cpu.LoadStateBinary(reader);
|
||||||
writer.Write(IOBuffer);
|
VCE.LoadStateBinary(reader);
|
||||||
Cpu.SaveStateBinary(writer);
|
VPC.LoadStateBinary(reader);
|
||||||
VCE.SaveStateBinary(writer);
|
VDC1.LoadStateBinary(reader);
|
||||||
VPC.SaveStateBinary(writer);
|
VDC2.LoadStateBinary(reader);
|
||||||
VDC1.SaveStateBinary(writer);
|
PSG.LoadStateBinary(reader);
|
||||||
VDC2.SaveStateBinary(writer);
|
}
|
||||||
PSG.SaveStateBinary(writer);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadStateBinary(BinaryReader reader)
|
public byte[] SaveStateBinary()
|
||||||
{
|
{
|
||||||
if (SuperGrafx == false)
|
int buflen = 75866;
|
||||||
{
|
if (SuperGrafx) buflen += 90698;
|
||||||
Ram = reader.ReadBytes(0x2000);
|
if (BramEnabled) buflen += 2048;
|
||||||
if (PopulousRAM != null)
|
if (PopulousRAM != null) buflen += 0x8000;
|
||||||
PopulousRAM = reader.ReadBytes(0x8000);
|
|
||||||
Frame = reader.ReadInt32();
|
|
||||||
_lagcount = reader.ReadInt32();
|
|
||||||
SF2MapperLatch = reader.ReadByte();
|
|
||||||
IOBuffer = reader.ReadByte();
|
|
||||||
Cpu.LoadStateBinary(reader);
|
|
||||||
VCE.LoadStateBinary(reader);
|
|
||||||
VDC1.LoadStateBinary(reader);
|
|
||||||
PSG.LoadStateBinary(reader);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Ram = reader.ReadBytes(0x8000);
|
|
||||||
Frame = reader.ReadInt32();
|
|
||||||
_lagcount = reader.ReadInt32();
|
|
||||||
IOBuffer = reader.ReadByte();
|
|
||||||
Cpu.LoadStateBinary(reader);
|
|
||||||
VCE.LoadStateBinary(reader);
|
|
||||||
VPC.LoadStateBinary(reader);
|
|
||||||
VDC1.LoadStateBinary(reader);
|
|
||||||
VDC2.LoadStateBinary(reader);
|
|
||||||
PSG.LoadStateBinary(reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] SaveStateBinary()
|
var buf = new byte[buflen];
|
||||||
{
|
var stream = new MemoryStream(buf);
|
||||||
int buflen = 75866;
|
var writer = new BinaryWriter(stream);
|
||||||
if (SuperGrafx) buflen += 90698;
|
SaveStateBinary(writer);
|
||||||
if (BramEnabled) buflen += 2048;
|
//Console.WriteLine("LENGTH " + stream.Position);
|
||||||
if (PopulousRAM != null) buflen += 0x8000;
|
writer.Close();
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
var buf = new byte[buflen];
|
private void SetupMemoryDomains()
|
||||||
var stream = new MemoryStream(buf);
|
{
|
||||||
var writer = new BinaryWriter(stream);
|
var domains = new List<MemoryDomain>(1);
|
||||||
SaveStateBinary(writer);
|
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
|
||||||
//Console.WriteLine("LENGTH " + stream.Position);
|
addr => Ram[addr & 0x7FFF],
|
||||||
writer.Close();
|
(addr, value) => Ram[addr & 0x7FFF] = value);
|
||||||
return buf;
|
var SystemBusDomain = new MemoryDomain("System Bus", 0x2F0000, Endian.Little,
|
||||||
}
|
addr => Cpu.ReadMemory21(addr),
|
||||||
|
(addr, value) => Cpu.WriteMemory21(addr, value));
|
||||||
|
domains.Add(MainMemoryDomain);
|
||||||
|
domains.Add(SystemBusDomain);
|
||||||
|
memoryDomains = domains.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
private void SetupMemoryDomains()
|
private IList<MemoryDomain> memoryDomains;
|
||||||
{
|
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||||
var domains = new List<MemoryDomain>(1);
|
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||||
var MainMemoryDomain = new MemoryDomain("Main Memory", Ram.Length, Endian.Little,
|
|
||||||
addr => Ram[addr & 0x7FFF],
|
|
||||||
(addr, value) => Ram[addr & 0x7FFF] = value);
|
|
||||||
var SystemBusDomain = new MemoryDomain("System Bus", 0x2F0000, Endian.Little,
|
|
||||||
addr => Cpu.ReadMemory21(addr),
|
|
||||||
(addr, value) => Cpu.WriteMemory21(addr, value));
|
|
||||||
domains.Add(MainMemoryDomain);
|
|
||||||
domains.Add(SystemBusDomain);
|
|
||||||
memoryDomains = domains.AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IList<MemoryDomain> memoryDomains;
|
public void Dispose() {}
|
||||||
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
}
|
||||||
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
|
||||||
|
|
||||||
public void Dispose() { }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
//TBD CCD format
|
//TBD CCD format
|
||||||
public class CCDFormat
|
public class CCDFormat
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
//this rule is not supported correctly: `The first track number can be greater than one, but all track numbers after the first must be sequential.`
|
//this rule is not supported correctly: `The first track number can be greater than one, but all track numbers after the first must be sequential.`
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
partial class Disc
|
partial class Disc
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,9 +3,8 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
//main apis for emulator core routine use
|
//main apis for emulator core routine use
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
|
|
||||||
public class DiscHopper
|
public class DiscHopper
|
||||||
{
|
{
|
||||||
public Disc CurrentDisc;
|
public Disc CurrentDisc;
|
||||||
|
@ -83,11 +82,31 @@ namespace BizHawk.Disc
|
||||||
return TOC;
|
return TOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// converts LBA to minute:second:frame format.
|
||||||
public static void ConvertLBAtoMSF(int lba, out byte m, out byte s, out byte f)
|
public static void ConvertLBAtoMSF(int lba, out byte m, out byte s, out byte f)
|
||||||
{
|
{
|
||||||
m = (byte) (lba / 75 / 60);
|
m = (byte) (lba / 75 / 60);
|
||||||
s = (byte) ((lba - (m * 75 * 60)) / 75);
|
s = (byte) ((lba - (m * 75 * 60)) / 75);
|
||||||
f = (byte) (lba - (m * 75 * 60) - (s * 75));
|
f = (byte) (lba - (m * 75 * 60) - (s * 75));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gets an identifying hash. hashes the first 512 sectors of
|
||||||
|
// the first data track on the disc.
|
||||||
|
public string GetHash()
|
||||||
|
{
|
||||||
|
byte[] buffer = new byte[512*2353];
|
||||||
|
foreach (var track in TOC.Sessions[0].Tracks)
|
||||||
|
{
|
||||||
|
if (track.TrackType == ETrackType.Audio)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int lba_len = Math.Min(track.length_lba, 512);
|
||||||
|
for (int s=0; s<512 && s<track.length_lba; s++)
|
||||||
|
ReadLBA_2352(track.Indexes[1].lba + s, buffer, s*2352);
|
||||||
|
|
||||||
|
return Util.Hash_MD5(buffer, 0, lba_len*2352);
|
||||||
|
}
|
||||||
|
return "no data track found";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -66,7 +66,7 @@ using System.Collections.Generic;
|
||||||
//mode2_2352 is the only kind of mode2, by necessity
|
//mode2_2352 is the only kind of mode2, by necessity
|
||||||
//audio is a different mode, seems to be just 2352 bytes with no sync, header or error correction. i guess the CIRC error correction is still there
|
//audio is a different mode, seems to be just 2352 bytes with no sync, header or error correction. i guess the CIRC error correction is still there
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
public partial class Disc
|
public partial class Disc
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@ using System.Text.RegularExpressions;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
|
|
||||||
public class DiscTOC
|
public class DiscTOC
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
static class ECM
|
static class ECM
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.Collections.Generic;
|
||||||
//a decent little subcode reference
|
//a decent little subcode reference
|
||||||
//http://www.jbum.com/cdg_revealed.html
|
//http://www.jbum.com/cdg_revealed.html
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
public class SubcodeStream
|
public class SubcodeStream
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BizHawk.Disc
|
namespace BizHawk.DiscSystem
|
||||||
{
|
{
|
||||||
//TBD TOC format
|
//TBD TOC format
|
||||||
public class TOCFormat
|
public class TOCFormat
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using BizHawk.DiscSystem;
|
||||||
|
|
||||||
namespace BizHawk
|
namespace BizHawk
|
||||||
{
|
{
|
||||||
|
@ -40,7 +41,7 @@ namespace BizHawk
|
||||||
base.Dispose();
|
base.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Disc.DiscHopper DiscHopper;
|
public DiscHopper DiscHopper;
|
||||||
|
|
||||||
void SetFp(string name, Delegate del)
|
void SetFp(string name, Delegate del)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +50,7 @@ namespace BizHawk
|
||||||
|
|
||||||
struct TrackInfo
|
struct TrackInfo
|
||||||
{
|
{
|
||||||
public Disc.ETrackType TrackType;
|
public ETrackType TrackType;
|
||||||
public int length_lba;
|
public int length_lba;
|
||||||
public int start_lba;
|
public int start_lba;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using BizHawk.DiscSystem;
|
||||||
|
|
||||||
namespace BizHawk
|
namespace BizHawk
|
||||||
{
|
{
|
||||||
|
@ -29,7 +30,7 @@ namespace BizHawk
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscInterface mDiscInterface;
|
DiscInterface mDiscInterface;
|
||||||
public void SetDiscHopper(Disc.DiscHopper hopper)
|
public void SetDiscHopper(DiscHopper hopper)
|
||||||
{
|
{
|
||||||
mDiscInterface.DiscHopper = hopper;
|
mDiscInterface.DiscHopper = hopper;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using SlimDX.Direct3D9;
|
using BizHawk.DiscSystem;
|
||||||
|
using SlimDX.Direct3D9;
|
||||||
using SlimDX.DirectSound;
|
using SlimDX.DirectSound;
|
||||||
|
|
||||||
namespace BizHawk.MultiClient
|
namespace BizHawk.MultiClient
|
||||||
|
@ -74,7 +75,7 @@ namespace BizHawk.MultiClient
|
||||||
return mg.GetControllersAsMnemonic();
|
return mg.GetControllersAsMnemonic();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Disc.DiscHopper DiscHopper = new BizHawk.Disc.DiscHopper();
|
public static DiscHopper DiscHopper = new DiscHopper();
|
||||||
|
|
||||||
|
|
||||||
public static CoreAccessor PsxCoreLibrary = new CoreAccessor(new Win32LibAccessor("PsxHawk.Core.dll"));
|
public static CoreAccessor PsxCoreLibrary = new CoreAccessor(new Win32LibAccessor("PsxHawk.Core.dll"));
|
||||||
|
|
|
@ -4,9 +4,9 @@ using System.Threading;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using BizHawk.Core;
|
using BizHawk.Core;
|
||||||
|
using BizHawk.DiscSystem;
|
||||||
using BizHawk.Emulation.Consoles.Sega;
|
using BizHawk.Emulation.Consoles.Sega;
|
||||||
using BizHawk.Emulation.Consoles.TurboGrafx;
|
using BizHawk.Emulation.Consoles.TurboGrafx;
|
||||||
using BizHawk.Emulation.Consoles.Calculator;
|
using BizHawk.Emulation.Consoles.Calculator;
|
||||||
|
@ -847,7 +847,7 @@ namespace BizHawk.MultiClient
|
||||||
PsxCore psx = new PsxCore(Global.PsxCoreLibrary);
|
PsxCore psx = new PsxCore(Global.PsxCoreLibrary);
|
||||||
nextEmulator = psx;
|
nextEmulator = psx;
|
||||||
game = new RomGame();
|
game = new RomGame();
|
||||||
var disc = Disc.Disc.FromIsoPath(path);
|
var disc = Disc.FromIsoPath(path);
|
||||||
Global.DiscHopper.Clear();
|
Global.DiscHopper.Clear();
|
||||||
Global.DiscHopper.Enqueue(disc);
|
Global.DiscHopper.Enqueue(disc);
|
||||||
Global.DiscHopper.Insert();
|
Global.DiscHopper.Insert();
|
||||||
|
|
Loading…
Reference in New Issue