BizHawk/ExternalCoreProjects/Virtu/Machine.cs

217 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Threading;
using Jellyfish.Virtu.Services;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace Jellyfish.Virtu
{
public sealed class Machine : IDisposable
{
/// <summary>
/// for deserialization only!!
/// </summary>
public Machine() { }
public Machine(byte[] appleIIe, byte[] diskIIRom)
{
Events = new MachineEvents();
Cpu = new Cpu(this);
Memory = new Memory(this, appleIIe);
Keyboard = new Keyboard(this);
GamePort = new GamePort(this);
Cassette = new Cassette(this);
Speaker = new Speaker(this);
Video = new Video(this);
NoSlotClock = new NoSlotClock(this);
var emptySlot = new PeripheralCard(this);
Slot1 = emptySlot;
Slot2 = emptySlot;
Slot3 = emptySlot;
Slot4 = emptySlot;
Slot5 = emptySlot;
Slot6 = new DiskIIController(this, diskIIRom);
Slot7 = emptySlot;
Slots = new List<PeripheralCard> { null, Slot1, Slot2, Slot3, Slot4, Slot5, Slot6, Slot7 };
Components = new List<MachineComponent> { Cpu, Memory, Keyboard, GamePort, Cassette, Speaker, Video, NoSlotClock, Slot1, Slot2, Slot3, Slot4, Slot5, Slot6, Slot7 };
BootDiskII = Slots.OfType<DiskIIController>().Last();
}
public void Dispose()
{
}
public void Reset()
{
foreach (var component in Components)
{
DebugService.WriteMessage("Resetting machine '{0}'", component.GetType().Name);
component.Reset();
//DebugService.WriteMessage("Reset machine '{0}'", component.GetType().Name);
}
}
private void Initialize()
{
foreach (var component in Components)
{
DebugService.WriteMessage("Initializing machine '{0}'", component.GetType().Name);
component.Initialize();
//DebugService.WriteMessage("Initialized machine '{0}'", component.GetType().Name);
}
}
private void Uninitialize()
{
foreach (var component in Components)
{
DebugService.WriteMessage("Uninitializing machine '{0}'", component.GetType().Name);
component.Uninitialize();
//DebugService.WriteMessage("Uninitialized machine '{0}'", component.GetType().Name);
}
}
public void BizInitialize()
{
Initialize();
Reset();
}
public void BizFrameAdvance(IEnumerable<string> buttons)
{
Lagged = true;
DriveLight = false;
Keyboard.SetKeys(buttons);
//frame begins at vsync.. beginning of vblank
while (Video.IsVBlank)
{
/*
var sb = new System.Text.StringBuilder();
sb.AppendFormat("{0} ", Cpu);
for (int i = 0; i < 256; i++)
sb.AppendFormat("{0:x2} ", Memory.Read(i));
tw.WriteLine(sb.ToString());*/
Events.HandleEvents(Cpu.Execute());
}
//now, while not vblank, we're in a frame
while (!Video.IsVBlank)
{
/*
var sb = new System.Text.StringBuilder();
sb.AppendFormat("{0} ", Cpu);
for (int i = 0; i < 256; i++)
sb.AppendFormat("{0:x2} ", Memory.Read(i));
tw.WriteLine(sb.ToString()); */
Events.HandleEvents(Cpu.Execute());
}
}
public void BizShutdown()
{
Uninitialize();
}
private static JsonSerializer CreateSerializer()
{
// TODO: converters could be cached for speedup
var ser = new JsonSerializer
{
TypeNameHandling = TypeNameHandling.Auto,
PreserveReferencesHandling = PreserveReferencesHandling.All, // leaving out Array is a very important problem, and means that we can't rely on a directly shared array to work.
ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
};
ser.Converters.Add(new TypeTypeConverter(new[]
{
// all expected Types to convert are either in this assembly or mscorlib
typeof(Machine).Assembly,
typeof(object).Assembly
}));
ser.Converters.Add(new DelegateConverter());
ser.Converters.Add(new ArrayConverter());
var cr = new DefaultContractResolver();
cr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
ser.ContractResolver = cr;
return ser;
}
public void Serialize(JsonWriter w)
{
CreateSerializer().Serialize(w, this);
}
public static Machine Deserialize(JsonReader r)
{
return CreateSerializer().Deserialize<Machine>(r);
}
public const string Version = "0.9.4.0";
public MachineEvents Events { get; private set; }
public Cpu Cpu { get; private set; }
public Memory Memory { get; private set; }
public Keyboard Keyboard { get; private set; }
public GamePort GamePort { get; private set; }
public Cassette Cassette { get; private set; }
public Speaker Speaker { get; private set; }
public Video Video { get; private set; }
public NoSlotClock NoSlotClock { get; private set; }
public PeripheralCard Slot1 { get; private set; }
public PeripheralCard Slot2 { get; private set; }
public PeripheralCard Slot3 { get; private set; }
public PeripheralCard Slot4 { get; private set; }
public PeripheralCard Slot5 { get; private set; }
public PeripheralCard Slot6 { get; private set; }
public PeripheralCard Slot7 { get; private set; }
public IList<PeripheralCard> Slots { get; private set; }
public IList<MachineComponent> Components { get; private set; }
public DiskIIController BootDiskII { get; private set; }
public bool Lagged { get; set; }
public bool DriveLight { get; set; }
public IDictionary<string, int> GetCpuFlagsAndRegisters()
{
return new Dictionary<string, int>
{
{ "A", Cpu.RA },
{ "X", Cpu.RX },
{ "Y", Cpu.RY },
{ "S", Cpu.RS },
{ "PC", Cpu.RPC },
{ "Flag C", Cpu.FlagC ? 1 : 0 },
{ "Flag Z", Cpu.FlagZ ? 1 : 0 },
{ "Flag I", Cpu.FlagI ? 1 : 0 },
{ "Flag D", Cpu.FlagD ? 1 : 0 },
{ "Flag B", Cpu.FlagB ? 1 : 0 },
{ "Flag V", Cpu.FlagV ? 1 : 0 },
{ "Flag N", Cpu.FlagN ? 1 : 0 },
{ "Flag T", Cpu.FlagT ? 1 : 0 }
};
}
}
}