PC Engine - break off services into their separate files

This commit is contained in:
adelikat 2016-12-12 10:23:07 -06:00
parent d78671a7e4
commit 618f5de54f
15 changed files with 671 additions and 472 deletions

View File

@ -140,6 +140,7 @@
<Compile Include="Interfaces\Services\ITraceable.cs" />
<Compile Include="Interfaces\Services\IVideoProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceAttributes.cs" />
<Compile Include="ServiceInjector.cs" />
<Compile Include="Sound\Utilities\BlipBuffer.cs" />
<Compile Include="Sound\Utilities\BufferedAsync.cs" />

View File

@ -910,8 +910,34 @@
<Compile Include="Consoles\PC Engine\MemoryMap.TurboCD.cs" />
<Compile Include="Consoles\PC Engine\MemoryMap.Populous.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ArcadeCard.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.CDLMapping.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ICodeDataLogger.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IDebuggable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IDriveLight.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IEmulator.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IInputPollable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IMemoryDomains.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.Input.cs" />
<Compile Include="Consoles\PC Engine\PCEngine.ISaveRam.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.ISettable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.IStatable.cs">
<DependentUpon>PCEngine.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\PC Engine\PCEngine.TurboCD.cs" />
<Compile Include="Consoles\PC Engine\ScsiCDBus.cs" />
<Compile Include="Consoles\Sega\Genesis\Cart\EEPROM.cs" />
@ -921,7 +947,7 @@
<Compile Include="Consoles\Sega\Genesis\Genesis.IO.cs" />
<Compile Include="Consoles\Sega\Genesis\Native68000\Musashi.cs" />
<Compile Include="Consoles\Sega\gpgx64\GPGX.ISoundProvider.cs">
<DependentUpon>GPGX.cs</DependentUpon>
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GenDbgHlp.cs" />
<Compile Include="Consoles\Sega\gpgx\GPGX.cs" />

View File

@ -1,15 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.H6280;
namespace BizHawk.Emulation.Cores.PCEngine
{
partial class PCEngine
public sealed partial class PCEngine : ICodeDataLogger
{
static void CDLMappingApplyRange(HuC6280.MemMapping[] mm, string name, int block, int len, int initialoffs = 0)
public void SetCDL(CodeDataLog cdl)
{
Cpu.CDL = cdl;
}
public void NewCDL(CodeDataLog cdl)
{
InitCDLMappings();
var mm = this.Cpu.Mappings;
foreach (var kvp in SizesFromHuMap(mm))
{
cdl[kvp.Key] = new byte[kvp.Value];
}
cdl.SubType = "PCE";
cdl.SubVer = 0;
}
public void DisassembleCDL(Stream s, CodeDataLog cdl)
{
Cpu.DisassembleCDL(s, cdl, _memoryDomains);
}
private static void CDLMappingApplyRange(HuC6280.MemMapping[] mm, string name, int block, int len, int initialoffs = 0)
{
for (int i = block, offs = initialoffs; i < 256 && len > (offs - initialoffs); i++, offs += 8192)
{
@ -21,10 +43,12 @@ namespace BizHawk.Emulation.Cores.PCEngine
/// <summary>
/// informs the CPU of the general memory layout, so it can do CDL
/// </summary>
public void InitCDLMappings()
private void InitCDLMappings()
{
if (Cpu.Mappings != null)
{
return;
}
SF2UpdateCDLMappings = true;
@ -32,7 +56,9 @@ namespace BizHawk.Emulation.Cores.PCEngine
CDLMappingApplyRange(mm, "ROM", 0x00, Math.Min(RomLength, 1024 * 1024));
if (PopulousRAM != null)
{
CDLMappingApplyRange(mm, "Cart Battery RAM", 0x40, PopulousRAM.Length);
}
// actual games came in 128K, 256K, 384K, 512K, 768K, 1024K, and Street Fighter sizes
// except street fighter, games were on 1 or 2 mask roms
@ -49,6 +75,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
mm[i].Name = null;
mm[i].Offs = 0;
}
for (int i = 0x40; i < 0x50; i++)
{
// rebase
@ -62,18 +89,23 @@ namespace BizHawk.Emulation.Cores.PCEngine
}
if (SuperRam != null)
{
CDLMappingApplyRange(mm, "Super System Card RAM", 0x68, SuperRam.Length);
}
if (CDRam != null)
{
CDLMappingApplyRange(mm, "TurboCD RAM", 0x80, CDRam.Length);
}
if (BRAM != null)
CDLMappingApplyRange(mm, "Battery RAM", 0xf7, BRAM.Length);
{
var rammirrors = new HuC6280.MemMapping { Name = "Main Memory", Offs = 0 };
mm[0xf9] = mm[0xfa] = mm[0xfb] = rammirrors;
CDLMappingApplyRange(mm, "Battery RAM", 0xf7, BRAM.Length);
}
var rammirrors = new HuC6280.MemMapping { Name = "Main Memory", Offs = 0 };
mm[0xf9] = mm[0xfa] = mm[0xfb] = rammirrors;
CDLMappingApplyRange(mm, "Main Memory", 0xf8, Ram.Length);
mm[0xff] = new HuC6280.MemMapping { Name = "MMIO", Offs = 0 };
@ -81,7 +113,9 @@ namespace BizHawk.Emulation.Cores.PCEngine
for (int i = 0; i < 256; i++)
{
if (mm[i].Name == null)
{
mm[i].Name = "UNKNOWN";
}
}
Cpu.Mappings = mm;

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : IDebuggable
{
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, RegisterValue>
{
{ "A", Cpu.A },
{ "X", Cpu.X },
{ "Y", Cpu.Y },
{ "PC", Cpu.PC },
{ "S", Cpu.S },
{ "MPR-0", Cpu.MPR[0] },
{ "MPR-1", Cpu.MPR[1] },
{ "MPR-2", Cpu.MPR[2] },
{ "MPR-3", Cpu.MPR[3] },
{ "MPR-4", Cpu.MPR[4] },
{ "MPR-5", Cpu.MPR[5] },
{ "MPR-6", Cpu.MPR[6] },
{ "MPR-7", Cpu.MPR[7] }
};
}
[FeatureNotImplemented]
public void SetCpuRegister(string register, int value)
{
throw new NotImplementedException();
}
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
public bool CanStep(StepType type) { return false; }
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
}
}

View File

@ -0,0 +1,11 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : IDriveLight
{
public bool DriveLightEnabled { get; private set; }
public bool DriveLightOn { get; internal set; }
}
}

View File

@ -0,0 +1,84 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : IEmulator
{
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public ControllerDefinition ControllerDefinition
{
get { return PCEngineController; }
}
public IController Controller { get; set; }
public void FrameAdvance(bool render, bool rendersound)
{
_lagged = true;
DriveLightOn = false;
Frame++;
CheckSpriteLimit();
PSG.BeginFrame(Cpu.TotalExecutedCycles);
Cpu.Debug = Tracer.Enabled;
if (SuperGrafx)
{
VPC.ExecFrame(render);
}
else
{
VDC1.ExecFrame(render);
}
PSG.EndFrame(Cpu.TotalExecutedCycles);
if (_lagged)
{
_lagCount++;
_isLag = true;
}
else
{
_isLag = false;
}
}
public int Frame
{
get { return frame; }
set { frame = value; }
}
public string SystemId { get; private set; }
public bool DeterministicEmulation
{
get { return true; }
}
public string BoardName
{
get { return null; }
}
public void ResetCounters()
{
// this should just be a public setter instead of a new method.
Frame = 0;
_lagCount = 0;
_isLag = false;
}
public CoreComm CoreComm { get; private set; }
public void Dispose()
{
if (disc != null)
{
disc.Dispose();
}
}
}
}

View File

@ -0,0 +1,29 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : IInputPollable
{
public int LagCount
{
get { return _lagCount; }
set { _lagCount = value; }
}
public bool IsLagFrame
{
get { return _isLag; }
set { _isLag = value; }
}
public IInputCallbackSystem InputCallbacks
{
get { return _inputCallbacks; }
}
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
private int _lagCount;
private bool _lagged = true;
private bool _isLag = false;
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine
{
private Dictionary<string, MemoryDomainByteArray> _byteArrayDomains = new Dictionary<string, MemoryDomainByteArray>();
private bool _memoryDomainsInit = false;
private MemoryDomainList _memoryDomains;
private void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>(2);
var SystemBusDomain = new MemoryDomainDelegate("System Bus (21 bit)", 0x200000, MemoryDomain.Endian.Little,
(addr) =>
{
if (addr < 0 || addr >= 0x200000)
throw new ArgumentOutOfRangeException();
return Cpu.ReadMemory21((int)addr);
},
(addr, value) =>
{
if (addr < 0 || addr >= 0x200000)
throw new ArgumentOutOfRangeException();
Cpu.WriteMemory21((int)addr, value);
},
wordSize: 2);
domains.Add(SystemBusDomain);
var CpuBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
(addr) =>
{
if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException();
return Cpu.ReadMemory((ushort)addr);
},
(addr, value) =>
{
if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException();
Cpu.WriteMemory((ushort)addr, value);
},
wordSize: 2);
domains.Add(CpuBusDomain);
SyncAllByteArrayDomains();
_memoryDomains = new MemoryDomainList(domains.Concat(_byteArrayDomains.Values).ToList());
_memoryDomains.SystemBus = CpuBusDomain;
_memoryDomains.MainMemory = _byteArrayDomains["Main Memory"];
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(_memoryDomains);
_memoryDomainsInit = true;
}
private void SyncAllByteArrayDomains()
{
SyncByteArrayDomain("Main Memory", Ram);
SyncByteArrayDomain("ROM", RomData);
if (BRAM != null)
SyncByteArrayDomain("Battery RAM", BRAM);
if (TurboCD)
{
SyncByteArrayDomain("TurboCD RAM", CDRam);
SyncByteArrayDomain("ADPCM RAM", ADPCM.RAM);
if (SuperRam != null)
{
SyncByteArrayDomain("Super System Card RAM", SuperRam);
}
}
if (ArcadeCard)
{
SyncByteArrayDomain("Arcade Card RAM", ArcadeRam);
}
if (PopulousRAM != null)
{
SyncByteArrayDomain("Cart Battery RAM", PopulousRAM);
}
}
private void SyncByteArrayDomain(string name, byte[] data)
{
if (_memoryDomainsInit)
{
var m = _byteArrayDomains[name];
m.Data = data;
}
else
{
var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1);
_byteArrayDomains.Add(name, m);
}
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : ISaveRam
{
public bool SaveRamModified { get; private set; }
public byte[] CloneSaveRam()
{
if (BRAM != null)
{
return (byte[])BRAM.Clone();
}
else
{
return null;
}
}
public void StoreSaveRam(byte[] data)
{
if (BRAM != null)
{
Array.Copy(data, BRAM, data.Length);
}
}
}
}

View File

@ -0,0 +1,100 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : ISettable<PCEngine.PCESettings, PCEngine.PCESyncSettings>
{
public PCESettings GetSettings()
{
return Settings.Clone();
}
public PCESyncSettings GetSyncSettings()
{
return _syncSettings.Clone();
}
public bool PutSettings(PCESettings o)
{
bool ret;
if (o.ArcadeCardRewindHack != Settings.ArcadeCardRewindHack
|| o.EqualizeVolume != Settings.EqualizeVolume)
{
ret = true;
}
else
{
ret = false;
}
Settings = o;
return ret;
}
public bool PutSyncSettings(PCESyncSettings o)
{
bool ret = PCESyncSettings.NeedsReboot(o, _syncSettings);
_syncSettings = o;
// SetControllerButtons(); // not safe to change the controller during emulation, so instead make it a reboot event
return ret;
}
internal PCESettings Settings;
private PCESyncSettings _syncSettings;
public class PCESettings
{
public bool ShowBG1 = true;
public bool ShowOBJ1 = true;
public bool ShowBG2 = true;
public bool ShowOBJ2 = true;
// these three require core reboot to use
public bool SpriteLimit = false;
public bool EqualizeVolume = false;
public bool ArcadeCardRewindHack = true;
public PCESettings Clone()
{
return (PCESettings)MemberwiseClone();
}
}
public class PCESyncSettings
{
public ControllerSetting[] Controllers =
{
new ControllerSetting { IsConnected = true },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false }
};
public PCESyncSettings Clone()
{
var ret = new PCESyncSettings();
for (int i = 0; i < Controllers.Length; i++)
{
ret.Controllers[i].IsConnected = Controllers[i].IsConnected;
}
return ret;
}
public class ControllerSetting
{
public bool IsConnected { get; set; }
}
public static bool NeedsReboot(PCESyncSettings x, PCESyncSettings y)
{
for (int i = 0; i < x.Controllers.Length; i++)
{
if (x.Controllers[i].IsConnected != y.Controllers[i].IsConnected)
return true;
}
return false;
}
}
}
}

View File

@ -0,0 +1,123 @@
using System.IO;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.PCEngine
{
public sealed partial class PCEngine : IStatable
{
public bool BinarySaveStatesPreferred
{
get { return false; }
}
public void SaveStateBinary(BinaryWriter bw)
{
SyncState(Serializer.CreateBinaryWriter(bw));
}
public void LoadStateBinary(BinaryReader br)
{
SyncState(Serializer.CreateBinaryReader(br));
}
public void SaveStateText(TextWriter tw)
{
SyncState(Serializer.CreateTextWriter(tw));
}
public void LoadStateText(TextReader tr)
{
SyncState(Serializer.CreateTextReader(tr));
}
public byte[] SaveStateBinary()
{
if (_stateBuffer == null)
{
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
_stateBuffer = stream.ToArray();
writer.Close();
return _stateBuffer;
}
else
{
var stream = new MemoryStream(_stateBuffer);
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
writer.Close();
return _stateBuffer;
}
}
private byte[] _stateBuffer;
private void SyncState(Serializer ser)
{
ser.BeginSection("PCEngine");
Cpu.SyncState(ser);
VCE.SyncState(ser);
VDC1.SyncState(ser, 1);
PSG.SyncState(ser);
if (SuperGrafx)
{
VPC.SyncState(ser);
VDC2.SyncState(ser, 2);
}
if (TurboCD)
{
ADPCM.SyncState(ser);
CDAudio.SyncState(ser);
SCSI.SyncState(ser);
ser.Sync("CDRAM", ref CDRam, false);
if (SuperRam != null)
{
ser.Sync("SuperRAM", ref SuperRam, false);
}
if (ArcadeCard)
{
ArcadeCardSyncState(ser);
}
}
ser.Sync("RAM", ref Ram, false);
ser.Sync("IOBuffer", ref IOBuffer);
ser.Sync("CdIoPorts", ref CdIoPorts, false);
ser.Sync("BramLocked", ref BramLocked);
ser.Sync("Frame", ref frame);
ser.Sync("Lag", ref _lagCount);
ser.Sync("IsLag", ref _isLag);
if (Cpu.ReadMemory21 == ReadMemorySF2)
{
ser.Sync("SF2MapperLatch", ref SF2MapperLatch);
}
if (PopulousRAM != null)
{
ser.Sync("PopulousRAM", ref PopulousRAM, false);
}
if (BRAM != null)
{
ser.Sync("BRAM", ref BRAM, false);
}
ser.EndSection();
if (ser.IsReader)
{
SyncAllByteArrayDomains();
}
}
}
}

View File

@ -41,9 +41,6 @@ namespace BizHawk.Emulation.Cores.PCEngine
}
}
public ControllerDefinition ControllerDefinition { get { return PCEngineController; } }
public IController Controller { get; set; }
int SelectedController;
byte InputByte;
@ -70,7 +67,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
int player = SelectedController + 1;
if (player < 6)
{
lagged = false;
_lagged = false;
if (SEL == false) // return buttons
{
if (Controller["P" + player + " B1"]) value &= 0xFE;

View File

@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BizHawk.Common;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Common.Components;
using BizHawk.Emulation.Cores.Components;
using BizHawk.Emulation.Cores.Components.H6280;
using BizHawk.Emulation.DiscSystem;
@ -26,46 +20,6 @@ namespace BizHawk.Emulation.Cores.PCEngine
public sealed partial class PCEngine : IEmulator, ISaveRam, IStatable, IInputPollable,
IDebuggable, ISettable<PCEngine.PCESettings, PCEngine.PCESyncSettings>, IDriveLight, ICodeDataLogger
{
// ROM
public byte[] RomData;
public int RomLength;
Disc disc;
// Machine
public NecSystemType Type;
public HuC6280 Cpu;
public VDC VDC1, VDC2;
public VCE VCE;
public VPC VPC;
public ScsiCDBus SCSI;
public ADPCM ADPCM;
public HuC6280PSG PSG;
public CDAudio CDAudio;
public SoundMixer SoundMixer;
//public MetaspuSoundProvider SoundSynchronizer;
bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
// BRAM
bool BramEnabled = false;
bool BramLocked = true;
byte[] BRAM;
// Memory system
public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram
public byte[] CDRam; // TurboCD extra 64k of ram
public byte[] SuperRam; // Super System Card 192K of additional RAM
public byte[] ArcadeRam; // Arcade Card 2048K of additional RAM
string systemid = "PCE";
bool ForceSpriteLimit;
// 21,477,270 Machine clocks / sec
// 7,159,090 Cpu cycles / sec
[CoreConstructor("PCE", "SGX")]
public PCEngine(CoreComm comm, GameInfo game, byte[] rom, object Settings, object syncSettings)
{
@ -75,37 +29,31 @@ namespace BizHawk.Emulation.Cores.PCEngine
switch (game.System)
{
default:
case "PCE":
systemid = "PCE";
SystemId = "PCE";
Type = NecSystemType.TurboGrafx;
break;
case "SGX":
systemid = "SGX";
SystemId = "SGX";
Type = NecSystemType.SuperGrafx;
break;
}
this._settings = (PCESettings)Settings ?? new PCESettings();
this.Settings = (PCESettings)Settings ?? new PCESettings();
_syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings();
Init(game, rom);
SetControllerButtons();
}
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public string BoardName { get { return null; } }
private ITraceable Tracer { get; set; }
public IMemoryCallbackSystem MemoryCallbacks { get; private set; }
public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings)
{
CoreComm = comm;
MemoryCallbacks = new MemoryCallbackSystem();
DriveLightEnabled = true;
systemid = "PCECD";
SystemId = "PCECD";
Type = NecSystemType.TurboCD;
this.disc = disc;
this._settings = (PCESettings)Settings ?? new PCESettings();
this.Settings = (PCESettings)Settings ?? new PCESettings();
_syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings();
GameInfo biosInfo;
@ -151,10 +99,48 @@ namespace BizHawk.Emulation.Cores.PCEngine
SetControllerButtons();
}
public bool DriveLightEnabled { get; private set; }
public bool DriveLightOn { get; internal set; }
// ROM
public byte[] RomData;
public int RomLength;
Disc disc;
void Init(GameInfo game, byte[] rom)
// Machine
public NecSystemType Type;
public HuC6280 Cpu;
public VDC VDC1, VDC2;
public VCE VCE;
public VPC VPC;
public ScsiCDBus SCSI;
public ADPCM ADPCM;
public HuC6280PSG PSG;
public CDAudio CDAudio;
public SoundMixer SoundMixer;
//public MetaspuSoundProvider SoundSynchronizer;
bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
bool TurboCD { get { return Type == NecSystemType.TurboCD; } }
// BRAM
bool BramEnabled = false;
bool BramLocked = true;
byte[] BRAM;
// Memory system
public byte[] Ram; // PCE= 8K base ram, SGX= 64k base ram
public byte[] CDRam; // TurboCD extra 64k of ram
public byte[] SuperRam; // Super System Card 192K of additional RAM
public byte[] ArcadeRam; // Arcade Card 2048K of additional RAM
bool ForceSpriteLimit;
// 21,477,270 Machine clocks / sec
// 7,159,090 Cpu cycles / sec
private ITraceable Tracer { get; set; }
private void Init(GameInfo game, byte[] rom)
{
Controller = NullController.GetNullController();
Cpu = new HuC6280(MemoryCallbacks);
@ -253,7 +239,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
{
ArcadeRam = new byte[0x200000];
ArcadeCard = true;
ArcadeCardRewindHack = _settings.ArcadeCardRewindHack;
ArcadeCardRewindHack = Settings.ArcadeCardRewindHack;
for (int i = 0; i < 4; i++)
ArcadePage[i] = new ArcadeCardPage();
}
@ -276,7 +262,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
if (game["AdpcmVol"])
ADPCM.MaxVolume = int.Parse(game.OptionValue("AdpcmVol"));
// the gamedb can also force equalizevolumes on
if (TurboCD && (_settings.EqualizeVolume || game["EqualizeVolumes"] || game.NotInDatabase))
if (TurboCD && (Settings.EqualizeVolume || game["EqualizeVolumes"] || game.NotInDatabase))
SoundMixer.EqualizeVolumes();
// Ok, yes, HBlankPeriod's only purpose is game-specific hax.
@ -308,404 +294,36 @@ namespace BizHawk.Emulation.Cores.PCEngine
SetupMemoryDomains();
}
int lagCount;
int frame;
bool lagged = true;
bool isLag = false;
public int Frame { get { return frame; } set { frame = value; } }
public int LagCount { get { return lagCount; } set { lagCount = value; } }
public bool IsLagFrame { get { return isLag; } set { isLag = value; } }
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
void ICodeDataLogger.SetCDL(CodeDataLog cdl)
{
Cpu.CDL = cdl;
}
void ICodeDataLogger.NewCDL(CodeDataLog cdl)
{
InitCDLMappings();
var mm = this.Cpu.Mappings;
foreach (var kvp in SizesFromHuMap(mm))
{
cdl[kvp.Key] = new byte[kvp.Value];
}
cdl.SubType = "PCE";
cdl.SubVer = 0;
}
void ICodeDataLogger.DisassembleCDL(Stream s, CodeDataLog cdl)
{
Cpu.DisassembleCDL(s, cdl, _memoryDomains);
}
private int frame;
private static Dictionary<string, int> SizesFromHuMap(IEnumerable<HuC6280.MemMapping> mm)
{
Dictionary<string, int> sizes = new Dictionary<string, int>();
foreach (var m in mm)
{
if (!sizes.ContainsKey(m.Name) || m.MaxOffs >= sizes[m.Name])
sizes[m.Name] = m.MaxOffs;
}
List<string> keys = new List<string>(sizes.Keys);
foreach (var key in keys)
{
// becase we were looking at offsets, and each bank is 8192 big, we need to add that size
sizes[key] += 8192;
}
return sizes;
}
public void ResetCounters()
{
// this should just be a public setter instead of a new method.
Frame = 0;
lagCount = 0;
isLag = false;
}
public void FrameAdvance(bool render, bool rendersound)
{
lagged = true;
DriveLightOn = false;
Frame++;
CheckSpriteLimit();
PSG.BeginFrame(Cpu.TotalExecutedCycles);
Cpu.Debug = Tracer.Enabled;
if (SuperGrafx)
VPC.ExecFrame(render);
else
VDC1.ExecFrame(render);
PSG.EndFrame(Cpu.TotalExecutedCycles);
if (lagged)
Dictionary<string, int> sizes = new Dictionary<string, int>();
foreach (var m in mm)
{
lagCount++;
isLag = true;
if (!sizes.ContainsKey(m.Name) || m.MaxOffs >= sizes[m.Name])
sizes[m.Name] = m.MaxOffs;
}
else
isLag = false;
var keys = new List<string>(sizes.Keys);
foreach (var key in keys)
{
// becase we were looking at offsets, and each bank is 8192 big, we need to add that size
sizes[key] += 8192;
}
return sizes;
}
void CheckSpriteLimit()
private void CheckSpriteLimit()
{
bool spriteLimit = ForceSpriteLimit | _settings.SpriteLimit;
bool spriteLimit = ForceSpriteLimit | Settings.SpriteLimit;
VDC1.PerformSpriteLimit = spriteLimit;
if (VDC2 != null)
VDC2.PerformSpriteLimit = spriteLimit;
}
public CoreComm CoreComm { get; private set; }
private ISoundProvider soundProvider;
public string SystemId { get { return systemid; } }
public string Region { get; set; }
public bool DeterministicEmulation { get { return true; } }
public byte[] CloneSaveRam()
{
if (BRAM != null)
return (byte[])BRAM.Clone();
else
return null;
}
public void StoreSaveRam(byte[] data)
{
if (BRAM != null)
Array.Copy(data, BRAM, data.Length);
}
public bool SaveRamModified { get; private set; }
public bool BinarySaveStatesPreferred { get { return false; } }
public void SaveStateBinary(BinaryWriter bw) { SyncState(Serializer.CreateBinaryWriter(bw)); }
public void LoadStateBinary(BinaryReader br) { SyncState(Serializer.CreateBinaryReader(br)); }
public void SaveStateText(TextWriter tw) { SyncState(Serializer.CreateTextWriter(tw)); }
public void LoadStateText(TextReader tr) { SyncState(Serializer.CreateTextReader(tr)); }
void SyncState(Serializer ser)
{
ser.BeginSection("PCEngine");
Cpu.SyncState(ser);
VCE.SyncState(ser);
VDC1.SyncState(ser, 1);
PSG.SyncState(ser);
if (SuperGrafx)
{
VPC.SyncState(ser);
VDC2.SyncState(ser, 2);
}
if (TurboCD)
{
ADPCM.SyncState(ser);
CDAudio.SyncState(ser);
SCSI.SyncState(ser);
ser.Sync("CDRAM", ref CDRam, false);
if (SuperRam != null)
ser.Sync("SuperRAM", ref SuperRam, false);
if (ArcadeCard)
ArcadeCardSyncState(ser);
}
ser.Sync("RAM", ref Ram, false);
ser.Sync("IOBuffer", ref IOBuffer);
ser.Sync("CdIoPorts", ref CdIoPorts, false);
ser.Sync("BramLocked", ref BramLocked);
ser.Sync("Frame", ref frame);
ser.Sync("Lag", ref lagCount);
ser.Sync("IsLag", ref isLag);
if (Cpu.ReadMemory21 == ReadMemorySF2)
ser.Sync("SF2MapperLatch", ref SF2MapperLatch);
if (PopulousRAM != null)
ser.Sync("PopulousRAM", ref PopulousRAM, false);
if (BRAM != null)
ser.Sync("BRAM", ref BRAM, false);
ser.EndSection();
if (ser.IsReader)
SyncAllByteArrayDomains();
}
byte[] stateBuffer;
public byte[] SaveStateBinary()
{
if (stateBuffer == null)
{
var stream = new MemoryStream();
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
stateBuffer = stream.ToArray();
writer.Close();
return stateBuffer;
}
else
{
var stream = new MemoryStream(stateBuffer);
var writer = new BinaryWriter(stream);
SaveStateBinary(writer);
writer.Flush();
writer.Close();
return stateBuffer;
}
}
void SetupMemoryDomains()
{
var domains = new List<MemoryDomain>(2);
var SystemBusDomain = new MemoryDomainDelegate("System Bus (21 bit)", 0x200000, MemoryDomain.Endian.Little,
(addr) =>
{
if (addr < 0 || addr >= 0x200000)
throw new ArgumentOutOfRangeException();
return Cpu.ReadMemory21((int)addr);
},
(addr, value) =>
{
if (addr < 0 || addr >= 0x200000)
throw new ArgumentOutOfRangeException();
Cpu.WriteMemory21((int)addr, value);
},
wordSize: 2);
domains.Add(SystemBusDomain);
var CpuBusDomain = new MemoryDomainDelegate("System Bus", 0x10000, MemoryDomain.Endian.Little,
(addr) =>
{
if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException();
return Cpu.ReadMemory((ushort)addr);
},
(addr, value) =>
{
if (addr < 0 || addr >= 0x10000)
throw new ArgumentOutOfRangeException();
Cpu.WriteMemory((ushort)addr, value);
},
wordSize: 2);
domains.Add(CpuBusDomain);
SyncAllByteArrayDomains();
_memoryDomains = new MemoryDomainList(domains.Concat(_byteArrayDomains.Values).ToList());
_memoryDomains.SystemBus = CpuBusDomain;
_memoryDomains.MainMemory = _byteArrayDomains["Main Memory"];
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(_memoryDomains);
_memoryDomainsInit = true;
}
private void SyncAllByteArrayDomains()
{
SyncByteArrayDomain("Main Memory", Ram);
SyncByteArrayDomain("ROM", RomData);
if (BRAM != null)
SyncByteArrayDomain("Battery RAM", BRAM);
if (TurboCD)
{
SyncByteArrayDomain("TurboCD RAM", CDRam);
SyncByteArrayDomain("ADPCM RAM", ADPCM.RAM);
if (SuperRam != null)
SyncByteArrayDomain("Super System Card RAM", SuperRam);
}
if (ArcadeCard)
SyncByteArrayDomain("Arcade Card RAM", ArcadeRam);
if (PopulousRAM != null)
SyncByteArrayDomain("Cart Battery RAM", PopulousRAM);
}
private void SyncByteArrayDomain(string name, byte[] data)
{
if (_memoryDomainsInit)
{
var m = _byteArrayDomains[name];
m.Data = data;
}
else
{
var m = new MemoryDomainByteArray(name, MemoryDomain.Endian.Little, data, true, 1);
_byteArrayDomains.Add(name, m);
}
}
private Dictionary<string, MemoryDomainByteArray> _byteArrayDomains = new Dictionary<string,MemoryDomainByteArray>();
private bool _memoryDomainsInit = false;
private MemoryDomainList _memoryDomains;
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, RegisterValue>
{
{ "A", Cpu.A },
{ "X", Cpu.X },
{ "Y", Cpu.Y },
{ "PC", Cpu.PC },
{ "S", Cpu.S },
{ "MPR-0", Cpu.MPR[0] },
{ "MPR-1", Cpu.MPR[1] },
{ "MPR-2", Cpu.MPR[2] },
{ "MPR-3", Cpu.MPR[3] },
{ "MPR-4", Cpu.MPR[4] },
{ "MPR-5", Cpu.MPR[5] },
{ "MPR-6", Cpu.MPR[6] },
{ "MPR-7", Cpu.MPR[7] }
};
}
public bool CanStep(StepType type) { return false; }
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
[FeatureNotImplemented]
public void SetCpuRegister(string register, int value)
{
throw new NotImplementedException();
}
public void Dispose()
{
if (disc != null)
disc.Dispose();
}
public PCESettings _settings;
private PCESyncSettings _syncSettings;
public PCESettings GetSettings() { return _settings.Clone(); }
public PCESyncSettings GetSyncSettings() { return _syncSettings.Clone(); }
public bool PutSettings(PCESettings o)
{
bool ret;
if (o.ArcadeCardRewindHack != _settings.ArcadeCardRewindHack ||
o.EqualizeVolume != _settings.EqualizeVolume)
ret = true;
else
ret = false;
_settings = o;
return ret;
}
public bool PutSyncSettings(PCESyncSettings o)
{
bool ret = PCESyncSettings.NeedsReboot(o, _syncSettings);
_syncSettings = o;
// SetControllerButtons(); // not safe to change the controller during emulation, so instead make it a reboot event
return ret;
}
public class PCESettings
{
public bool ShowBG1 = true;
public bool ShowOBJ1 = true;
public bool ShowBG2 = true;
public bool ShowOBJ2 = true;
// these three require core reboot to use
public bool SpriteLimit = false;
public bool EqualizeVolume = false;
public bool ArcadeCardRewindHack = true;
public PCESettings Clone()
{
return (PCESettings)MemberwiseClone();
}
}
public class PCESyncSettings
{
public ControllerSetting[] Controllers =
{
new ControllerSetting { IsConnected = true },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false },
new ControllerSetting { IsConnected = false }
};
public PCESyncSettings Clone()
{
var ret = new PCESyncSettings();
for (int i = 0; i < Controllers.Length; i++)
{
ret.Controllers[i].IsConnected = Controllers[i].IsConnected;
}
return ret;
}
public class ControllerSetting
{
public bool IsConnected { get; set; }
}
public static bool NeedsReboot(PCESyncSettings x, PCESyncSettings y)
{
for (int i = 0; i < x.Controllers.Length; i++)
{
if (x.Controllers[i].IsConnected != y.Controllers[i].IsConnected)
return true;
}
return false;
}
}
}
}

View File

@ -108,8 +108,8 @@ namespace BizHawk.Emulation.Cores.PCEngine
if (ActiveLine >= FrameHeight)
return;
RenderBackgroundScanline(pce._settings.ShowBG1);
RenderSpritesScanline(pce._settings.ShowOBJ1);
RenderBackgroundScanline(pce.Settings.ShowBG1);
RenderSpritesScanline(pce.Settings.ShowOBJ1);
}
Action<bool> RenderBackgroundScanline;

View File

@ -246,16 +246,16 @@ namespace BizHawk.Emulation.Cores.PCEngine
switch (EffectivePriorityMode)
{
case 0:
RenderBackgroundScanline(VDC1, 12, PCE._settings.ShowBG1);
RenderBackgroundScanline(VDC2, 2, PCE._settings.ShowBG2);
RenderSpritesScanline(VDC1, 11, 14, PCE._settings.ShowOBJ1);
RenderSpritesScanline(VDC2, 1, 3, PCE._settings.ShowOBJ2);
RenderBackgroundScanline(VDC1, 12, PCE.Settings.ShowBG1);
RenderBackgroundScanline(VDC2, 2, PCE.Settings.ShowBG2);
RenderSpritesScanline(VDC1, 11, 14, PCE.Settings.ShowOBJ1);
RenderSpritesScanline(VDC2, 1, 3, PCE.Settings.ShowOBJ2);
break;
case 1:
RenderBackgroundScanline(VDC1, 12, PCE._settings.ShowBG1);
RenderBackgroundScanline(VDC2, 2, PCE._settings.ShowBG2);
RenderSpritesScanline(VDC1, 11, 14, PCE._settings.ShowOBJ1);
RenderSpritesScanline(VDC2, 1, 13, PCE._settings.ShowOBJ2);
RenderBackgroundScanline(VDC1, 12, PCE.Settings.ShowBG1);
RenderBackgroundScanline(VDC2, 2, PCE.Settings.ShowBG2);
RenderSpritesScanline(VDC1, 11, 14, PCE.Settings.ShowOBJ1);
RenderSpritesScanline(VDC2, 1, 13, PCE.Settings.ShowOBJ2);
break;
}
}