using System.Collections.Generic; namespace BizHawk.Emulation.Common { /// /// This service manages debugging capabilities from the core to the client. Tools such as the debugger make use of this, as well as LUA scripting /// This service specifically manages getting/setting CPU registers, managing breakpoints, and stepping through CPU instructions /// Providing a disassembly is managed by another service, these are aspects outside of the disassembler that are essential to debugging tools /// Tools like the debugger will gracefully degrade based on the availability of each component of this service, /// it is expected that any of these features will throw a NotImplementedException if not implemented, and the client will manage accordingly /// public interface IDebuggable : IEmulatorService { /// /// Returns a list of CPU registers and their current state /// IDictionary GetCpuFlagsAndRegisters(); /// /// Sets a given CPU register to the given value /// void SetCpuRegister(string register, int value); /// /// Gets a memory callback implementation that manages memory callback functionality /// IMemoryCallbackSystem MemoryCallbacks { get; } /// /// Informs the calling code whether or not the given step type is implemented, /// if false, a NotImplementedException will be thrown if Step is called with the given value /// bool CanStep(StepType type); /// /// Advances the core based on the given Step type /// void Step(StepType type); /// /// Gets the total number of CPU cycles since the beginning of the core's lifecycle /// Note that the CPU in this case is the "main" CPU, for some cores that may be somewhat subjective /// int TotalExecutedCycles { get; } // TODO: this should probably be a long, but most cores were using int, oh well } public class RegisterValue { public ulong Value { get; private set; } public byte BitSize { get; private set; } public RegisterValue(ulong val, byte bitSize) { if (bitSize == 64) { Value = val; } else if (bitSize > 64 || bitSize == 0) { throw new System.ArgumentOutOfRangeException(nameof(bitSize), "BitSize must be in 1..64"); } else { Value = val & (1UL << bitSize) - 1; } BitSize = bitSize; } public RegisterValue(bool val) { Value = val ? 1UL : 0UL; BitSize = 1; } public RegisterValue(byte val) { Value = val; BitSize = 8; } public RegisterValue(sbyte val) { Value = (byte)val; BitSize = 8; } public RegisterValue(ushort val) { Value = val; BitSize = 16; } public RegisterValue(short val) { Value = (ushort)val; BitSize = 16; } public RegisterValue(uint val) { Value = val; BitSize = 32; } public RegisterValue(int val) { Value = (uint)val; BitSize = 32; } public RegisterValue(ulong val) { Value = val; BitSize = 64; } public RegisterValue(long val) { Value = (ulong)val; BitSize = 64; } public static implicit operator RegisterValue(bool val) { return new RegisterValue(val); } public static implicit operator RegisterValue(byte val) { return new RegisterValue(val); } public static implicit operator RegisterValue(sbyte val) { return new RegisterValue(val); } public static implicit operator RegisterValue(ushort val) { return new RegisterValue(val); } public static implicit operator RegisterValue(short val) { return new RegisterValue(val); } public static implicit operator RegisterValue(uint val) { return new RegisterValue(val); } public static implicit operator RegisterValue(int val) { return new RegisterValue(val); } public static implicit operator RegisterValue(ulong val) { return new RegisterValue(val); } public static implicit operator RegisterValue(long val) { return new RegisterValue(val); } } }