mirror of
https://github.com/fadden/6502bench.git
synced 2024-08-17 07:29:01 +00:00
This adds a window that displays all of the instructions for a given CPU in a summary grid. Undocumented instructions are included, but shown in grey italics. Also, tweaked AppSettings to not mark itself as dirty if a "set" operation doesn't actually change anything.
185 lines
6.6 KiB
C#
185 lines
6.6 KiB
C#
/*
|
|
* Copyright 2019 faddenSoft
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
|
|
using Asm65;
|
|
|
|
namespace SourceGen.Tools.WpfGui {
|
|
/// <summary>
|
|
/// CPU instruction chart.
|
|
/// </summary>
|
|
public partial class InstructionChart : Window, INotifyPropertyChanged {
|
|
/// <summary>
|
|
/// Item for CPU selection combo box.
|
|
/// </summary>
|
|
public class CpuItem {
|
|
public string Name { get; private set; }
|
|
public CpuDef.CpuType Type { get; private set; }
|
|
|
|
public CpuItem(string name, CpuDef.CpuType type) {
|
|
Name = name;
|
|
Type = type;
|
|
}
|
|
}
|
|
public CpuItem[] CpuItems { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Item for main list.
|
|
/// </summary>
|
|
public class InstructionItem {
|
|
public string Opcode { get; private set; }
|
|
public string Sample { get; private set; }
|
|
public string Flags { get; private set; }
|
|
public string Cycles { get; private set; }
|
|
public string ShortDesc { get; private set; }
|
|
public string AddressMode { get; private set; }
|
|
|
|
public bool IsUndocumented { get; private set; }
|
|
|
|
public InstructionItem(string opcode, string sample, string flags, string cycles,
|
|
string shortDesc, string addrMode, bool isUndoc) {
|
|
Opcode = opcode;
|
|
Sample = sample;
|
|
Flags = flags;
|
|
Cycles = cycles;
|
|
ShortDesc = shortDesc;
|
|
AddressMode = addrMode;
|
|
IsUndocumented = isUndoc;
|
|
}
|
|
}
|
|
|
|
public ObservableCollection<InstructionItem> InstructionItems { get; private set; } =
|
|
new ObservableCollection<InstructionItem>();
|
|
|
|
private OpDescription mOpDesc = OpDescription.GetOpDescription(null);
|
|
|
|
private Formatter mFormatter;
|
|
|
|
// INotifyPropertyChanged implementation
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// </summary>
|
|
public InstructionChart(Window owner, Formatter formatter) {
|
|
InitializeComponent();
|
|
Owner = owner;
|
|
DataContext = this;
|
|
|
|
mFormatter = formatter;
|
|
|
|
CpuItems = new CpuItem[] {
|
|
new CpuItem((string)FindResource("str_6502"), CpuDef.CpuType.Cpu6502),
|
|
new CpuItem((string)FindResource("str_65C02"), CpuDef.CpuType.Cpu65C02),
|
|
new CpuItem((string)FindResource("str_65816"), CpuDef.CpuType.Cpu65816),
|
|
};
|
|
}
|
|
|
|
public void Window_Loaded(object sender, RoutedEventArgs e) {
|
|
// Restore chart mode setting.
|
|
CpuDef.CpuType type = (CpuDef.CpuType)AppSettings.Global.GetEnum(
|
|
AppSettings.ASCCH_MODE, typeof(CpuDef.CpuType), (int)CpuDef.CpuType.Cpu6502);
|
|
int index = 0;
|
|
for (int i = 0; i < CpuItems.Length; i++) {
|
|
if (CpuItems[i].Type == type) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
cpuSelectionComboBox.SelectedIndex = index;
|
|
}
|
|
|
|
// Catch ESC key.
|
|
private void Window_KeyEventHandler(object sender, KeyEventArgs e) {
|
|
if (e.Key == Key.Escape) {
|
|
Close();
|
|
}
|
|
}
|
|
|
|
private void CpuSelectionComboBox_SelectionChanged(object sender,
|
|
SelectionChangedEventArgs e) {
|
|
UpdateControls();
|
|
}
|
|
|
|
private void UpdateControls() {
|
|
CpuItem item = (CpuItem)cpuSelectionComboBox.SelectedItem;
|
|
if (item == null) {
|
|
// initializing
|
|
return;
|
|
}
|
|
|
|
// Push current choice to settings.
|
|
AppSettings.Global.SetEnum(AppSettings.ASCCH_MODE, typeof(CpuDef.CpuType),
|
|
(int)item.Type);
|
|
|
|
// Populate the items source.
|
|
InstructionItems.Clear();
|
|
CpuDef cpuDef = CpuDef.GetBestMatch(item.Type, true, false);
|
|
for (int i = 0; i < 256; i++) {
|
|
OpDef op = cpuDef[i];
|
|
|
|
int opLen = op.GetLength(StatusFlags.AllIndeterminate);
|
|
string sampleValue = "$12";
|
|
if (op.AddrMode == OpDef.AddressMode.BlockMove) {
|
|
sampleValue = "#$12,#$34";
|
|
} else if (opLen == 3) {
|
|
sampleValue = "$1234";
|
|
} else if (opLen == 4) {
|
|
sampleValue = "$123456";
|
|
}
|
|
string instrSample = op.Mnemonic + " " +
|
|
mFormatter.FormatOperand(op, sampleValue, OpDef.WidthDisambiguation.None);
|
|
|
|
|
|
StringBuilder flags = new StringBuilder(8);
|
|
const string FLAGS = "NVMXDIZC";
|
|
Asm65.StatusFlags affectedFlags = op.FlagsAffected;
|
|
for (int fl = 0; fl < 8; fl++) {
|
|
if (affectedFlags.GetBit((StatusFlags.FlagBits)(7 - fl)) >= 0) {
|
|
flags.Append(FLAGS[fl]);
|
|
} else {
|
|
flags.Append("-");
|
|
}
|
|
}
|
|
|
|
string cycles = op.Cycles.ToString();
|
|
if (op.CycleMods != 0) {
|
|
cycles += '+';
|
|
}
|
|
|
|
InstructionItems.Add(new InstructionItem(mFormatter.FormatHexValue(i, 2),
|
|
instrSample, flags.ToString(), cycles,
|
|
mOpDesc.GetShortDescription(op.Mnemonic),
|
|
mOpDesc.GetAddressModeDescription(op.AddrMode),
|
|
op.IsUndocumented));
|
|
}
|
|
}
|
|
}
|
|
}
|