using System; using System.Linq; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.IEmulatorExtensions; namespace BizHawk.Client.EmuHawk { public partial class CheatEdit : UserControl { public IMemoryDomains MemoryDomains { get; set; } public CheatEdit() { InitializeComponent(); AddressBox.Nullable = false; ValueBox.Nullable = false; } #region Privates private const string HexInd = "0x"; private Cheat _cheat; private bool _loading; private bool _editmode; private Action _addCallback; private Action _editCallback; private void CheatEdit_Load(object sender, EventArgs e) { if (MemoryDomains != null) // the designer needs this check { DomainDropDown.Items.Clear(); DomainDropDown.Items.AddRange(MemoryDomains .Where(d => d.CanPoke()) .Select(d => d.ToString()) .ToArray()); if (MemoryDomains.HasSystemBus) { DomainDropDown.SelectedItem = MemoryDomains.SystemBus.ToString(); } else { DomainDropDown.SelectedItem = MemoryDomains.MainMemory.ToString(); } } SetFormToDefault(); } private void SetFormToCheat() { _loading = true; SetSizeSelected(_cheat.Size); PopulateTypeDropdown(); SetTypeSelected(_cheat.Type); SetDomainSelected(_cheat.Domain); AddressBox.SetHexProperties(_cheat.Domain.Size); NameBox.Text = _cheat.Name; AddressBox.Text = _cheat.AddressStr; ValueBox.Text = _cheat.ValueStr; CompareBox.Text = _cheat.Compare.HasValue ? _cheat.CompareStr : String.Empty; ValueBox.ByteSize = CompareBox.ByteSize = _cheat.Size; ValueBox.Type = CompareBox.Type = _cheat.Type; ValueHexIndLabel.Text = CompareHexIndLabel.Text = _cheat.Type == Watch.DisplayType.Hex ? HexInd : string.Empty; BigEndianCheckBox.Checked = _cheat.BigEndian.Value; CheckFormState(); if (!_cheat.Compare.HasValue) { CompareBox.Text = String.Empty; // Necessary hack until WatchValueBox.ToRawInt() becomes nullable } _loading = false; } private void SetFormToDefault() { _loading = true; SetSizeSelected(Watch.WatchSize.Byte); PopulateTypeDropdown(); NameBox.Text = string.Empty; if (MemoryDomains != null) { AddressBox.SetHexProperties(MemoryDomains.SystemBus.Size); } ValueBox.ByteSize = CompareBox.ByteSize = Watch.WatchSize.Byte; ValueBox.Type = CompareBox.Type = Watch.DisplayType.Hex; ValueBox.ResetText(); CompareBox.ResetText(); ValueHexIndLabel.Text = CompareHexIndLabel.Text = HexInd; BigEndianCheckBox.Checked = false; SetTypeSelected(Watch.DisplayType.Hex); CheckFormState(); CompareBox.Text = string.Empty; // TODO: A needed hack until WatchValueBox.ToRawInt() becomes nullable _loading = false; } private void SetSizeSelected(Watch.WatchSize size) { switch (size) { default: case Watch.WatchSize.Byte: SizeDropDown.SelectedIndex = 0; break; case Watch.WatchSize.Word: SizeDropDown.SelectedIndex = 1; break; case Watch.WatchSize.DWord: SizeDropDown.SelectedIndex = 2; break; } } private void SetTypeSelected(Watch.DisplayType type) { foreach (var item in DisplayTypeDropDown.Items) { if (item.ToString() == Watch.DisplayTypeToString(type)) { DisplayTypeDropDown.SelectedItem = item; return; } } } private void SetDomainSelected(MemoryDomain domain) { foreach (var item in DomainDropDown.Items) { if (item.ToString() == domain.Name) { DomainDropDown.SelectedItem = item; return; } } } private void PopulateTypeDropdown() { DisplayTypeDropDown.Items.Clear(); switch (SizeDropDown.SelectedIndex) { default: case 0: DisplayTypeDropDown.Items.AddRange(ByteWatch.ValidTypes.ConvertAll(e => Watch.DisplayTypeToString(e)).ToArray()); break; case 1: DisplayTypeDropDown.Items.AddRange(WordWatch.ValidTypes.ConvertAll(e => Watch.DisplayTypeToString(e)).ToArray()); break; case 2: DisplayTypeDropDown.Items.AddRange(DWordWatch.ValidTypes.ConvertAll(e => Watch.DisplayTypeToString(e)).ToArray()); break; } DisplayTypeDropDown.SelectedItem = DisplayTypeDropDown.Items[0]; } private void CheckFormState() { var valid = !String.IsNullOrWhiteSpace(AddressBox.Text) && !String.IsNullOrWhiteSpace(ValueBox.Text); AddButton.Enabled = valid; EditButton.Enabled = _editmode && valid; } private void SizeDropDown_SelectedIndexChanged(object sender, EventArgs e) { if (!_loading) { PopulateTypeDropdown(); ValueBox.ByteSize = CompareBox.ByteSize = GetCurrentSize(); } } private void DomainDropDown_SelectedIndexChanged(object sender, EventArgs e) { if (!_loading) { var domain = MemoryDomains[DomainDropDown.SelectedItem.ToString()]; AddressBox.SetHexProperties(domain.Size); } } private Watch.WatchSize GetCurrentSize() { switch (SizeDropDown.SelectedIndex) { default: case 0: return Watch.WatchSize.Byte; case 1: return Watch.WatchSize.Word; case 2: return Watch.WatchSize.DWord; } } private void DisplayTypeDropDown_SelectedIndexChanged(object sender, EventArgs e) { ValueBox.Type = CompareBox.Type = Watch.StringToDisplayType(DisplayTypeDropDown.SelectedItem.ToString()); } private void AddButton_Click(object sender, EventArgs e) { if (_addCallback != null) { _addCallback(); } } private void EditButton_Click(object sender, EventArgs e) { if (_editCallback != null) { _editCallback(); } } #endregion #region API public void SetCheat(Cheat cheat) { _editmode = true; _cheat = cheat; if (cheat.IsSeparator) { SetFormToDefault(); } else { SetFormToCheat(); } } public void ClearForm() { _cheat = Cheat.Separator; _editmode = false; SetFormToDefault(); } public Cheat OriginalCheat { get { return _cheat; } } public Cheat Cheat { get { var domain = MemoryDomains[DomainDropDown.SelectedItem.ToString()]; var address = AddressBox.ToRawInt().Value; //var address = AddressBox.ToRawInt() ?? 0; if (address < domain.Size) { var watch = Watch.GenerateWatch( MemoryDomains[DomainDropDown.SelectedItem.ToString()], AddressBox.ToRawInt().Value, GetCurrentSize(), Watch.StringToDisplayType(DisplayTypeDropDown.SelectedItem.ToString()), NameBox.Text, BigEndianCheckBox.Checked); return new Cheat( watch, ValueBox.ToRawInt().Value, CompareBox.ToRawInt() ); } else { MessageBox.Show(address.ToString() + " is not a valid address for the domain " + domain.Name, "Index out of range", MessageBoxButtons.OK, MessageBoxIcon.Warning); return Cheat.Separator; } } } public void SetAddEvent(Action addCallback) { _addCallback = addCallback; } public void SetEditEvent(Action editCallback) { _editCallback = editCallback; } #endregion } }