summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--WPZX81.sln12
-rw-r--r--WPZX81/WPZX81/BaseViewModel.cs67
-rw-r--r--WPZX81/WPZX81/DisassemblerLine.cs34
-rw-r--r--WPZX81/WPZX81/DisassemblerPage.xaml226
-rw-r--r--WPZX81/WPZX81/DisassemblerPage.xaml.cs50
-rw-r--r--WPZX81/WPZX81/DisassemblerViewModel.cs258
-rw-r--r--WPZX81/WPZX81/MainPage.xaml4
-rw-r--r--WPZX81/WPZX81/MainPage.xaml.cs4
-rw-r--r--WPZX81/WPZX81/Resources/Strings.Designer.cs63
-rw-r--r--WPZX81/WPZX81/Resources/Strings.resx17
-rw-r--r--WPZX81/WPZX81/WPZX81.csproj14
-rw-r--r--WPZX81/WPZX81/ZX81/Emulation.cs98
12 files changed, 790 insertions, 57 deletions
diff --git a/WPZX81.sln b/WPZX81.sln
index 1a860f0..4d26e48 100644
--- a/WPZX81.sln
+++ b/WPZX81.sln
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit.Z80", "..\Noddybox.Emulation\WindowsPhone\Noddybox.Emulation.EightBit.Z80\Noddybox.Emulation.EightBit.Z80.csproj", "{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Noddybox.Emulation.EightBit.Z80.Disassembler", "..\Noddybox.Emulation\WindowsPhone\Noddybox.Emulation.EightBit.Z80.Disassembler\Noddybox.Emulation.EightBit.Z80.Disassembler.csproj", "{08D7120E-3D84-49D2-B73D-255E5DB9655C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -83,6 +85,16 @@ Global
{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}.Release|Windows Phone.ActiveCfg = Release|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Debug|Windows Phone.ActiveCfg = Debug|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {08D7120E-3D84-49D2-B73D-255E5DB9655C}.Release|Windows Phone.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/WPZX81/WPZX81/BaseViewModel.cs b/WPZX81/WPZX81/BaseViewModel.cs
new file mode 100644
index 0000000..ae729e6
--- /dev/null
+++ b/WPZX81/WPZX81/BaseViewModel.cs
@@ -0,0 +1,67 @@
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace WPZX81
+{
+ /// <summary>
+ /// Provides a base for view models.
+ /// </summary>
+ public class BaseViewModel : INotifyPropertyChanged
+ {
+
+ #region SetValue
+
+ /// <summary>
+ /// Sets a value in the model.
+ /// </summary>
+ /// <typeparam name="T">The type of the value.</typeparam>
+ /// <param name="member">A reference to the member variable.</param>
+ /// <param name="value">The new value.</param>
+ /// <param name="names">The propertys to change if the value has changed.</param>
+ protected void SetValue<T>(ref T member, T value, params string[] names)
+ {
+ if (!value.Equals(member))
+ {
+ member = value;
+
+ foreach (string name in names)
+ {
+ NotifyPropertyChanged(name);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Notify
+
+ /// <summary>
+ /// Notifies handlers of a property change.
+ /// </summary>
+ /// <param name="propertyName">The property's name.</param>
+ protected void NotifyPropertyChanged(string propertyName)
+ {
+ if (PropertyChanged != null)
+ {
+ PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ #endregion
+
+ #region INotifyPropertyChanged Members
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+}
diff --git a/WPZX81/WPZX81/DisassemblerLine.cs b/WPZX81/WPZX81/DisassemblerLine.cs
new file mode 100644
index 0000000..6618fc1
--- /dev/null
+++ b/WPZX81/WPZX81/DisassemblerLine.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace WPZX81
+{
+ /// <summary>
+ /// Represents a line of disassembly.
+ /// </summary>
+ public class DisassemblerLine
+ {
+ /// <summary>
+ /// The address part.
+ /// </summary>
+ public string Address {get; set;}
+
+ /// <summary>
+ /// The assembly opcode part.
+ /// </summary>
+ public string Opcode {get; set;}
+
+ /// <summary>
+ /// The hexdump part.
+ /// </summary>
+ public string Hexdump {get; set;}
+ }
+}
diff --git a/WPZX81/WPZX81/DisassemblerPage.xaml b/WPZX81/WPZX81/DisassemblerPage.xaml
new file mode 100644
index 0000000..3c87af6
--- /dev/null
+++ b/WPZX81/WPZX81/DisassemblerPage.xaml
@@ -0,0 +1,226 @@
+<phone:PhoneApplicationPage
+ x:Class="WPZX81.DisassemblerPage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
+ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:res="clr-namespace:WPZX81.Resources"
+ FontFamily="{StaticResource PhoneFontFamilyNormal}"
+ FontSize="{StaticResource PhoneFontSizeNormal}"
+ Foreground="{StaticResource PhoneForegroundBrush}"
+ SupportedOrientations="Portrait" Orientation="Portrait"
+ mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="480"
+ shell:SystemTray.IsVisible="False">
+
+ <phone:PhoneApplicationPage.Resources>
+ <res:Strings x:Key="Strings" />
+ <Style x:Name="StateInfo" TargetType="TextBlock">
+ <Setter Property="FontSize" Value="18" />
+ <Setter Property="FontWeight" Value="Bold" />
+ <Setter Property="Foreground" Value="White" />
+ </Style>
+ <Style x:Name="StateData" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Courier New" />
+ <Setter Property="FontSize" Value="18" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="Foreground" Value="White" />
+ </Style>
+ <Style x:Name="DisassemMemory" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Courier New" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="Foreground" Value="Yellow" />
+ </Style>
+ <Style x:Name="DisassemOpcode" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Courier New" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="Foreground" Value="White" />
+ </Style>
+ <Style x:Name="DisassemHexdump" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Courier New" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="Foreground" Value="Red" />
+ </Style>
+ </phone:PhoneApplicationPage.Resources>
+
+ <!--LayoutRoot is the root grid where all page content is placed-->
+ <Grid x:Name="LayoutRoot" Background="Transparent">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <!--TitlePanel contains the name of the application and page title-->
+ <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
+ <TextBlock x:Name="ApplicationTitle"
+ Text="{Binding AppTitle, Source={StaticResource Strings}}"
+ Style="{StaticResource PhoneTextNormalStyle}"/>
+ <TextBlock x:Name="PageTitle"
+ Text="{Binding DisassemblerPageTitle, Source={StaticResource Strings}}"
+ Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
+ </StackPanel>
+
+ <!--ContentPanel - place additional content here-->
+ <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ </Grid.ColumnDefinitions>
+
+ <!-- Z80 State -->
+ <Grid Grid.Row="0" Grid.ColumnSpan="2">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ <ColumnDefinition Width="1*" />
+ </Grid.ColumnDefinitions>
+
+ <TextBlock Style="{StaticResource StateInfo}" Text="A"
+ Grid.Row="0" Grid.Column="0" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="Flags"
+ Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="BC"
+ Grid.Row="0" Grid.Column="3" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="DE"
+ Grid.Row="0" Grid.Column="4" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="HL"
+ Grid.Row="0" Grid.Column="5" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="PC"
+ Grid.Row="0" Grid.Column="6" />
+
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding A, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="0"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding Flags, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding BC, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="3"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding DE, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="4"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding HL, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="5"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding PC, Mode=OneWay}"
+ Grid.Row="1" Grid.Column="6"/>
+
+ <TextBlock Style="{StaticResource StateInfo}" Text="IY"
+ Grid.Row="0" Grid.Column="6" />
+
+
+ <TextBlock Style="{StaticResource StateInfo}" Text="IX"
+ Grid.Row="2" Grid.Column="0" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="IY"
+ Grid.Row="2" Grid.Column="1" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="SP"
+ Grid.Row="2" Grid.Column="2" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="AF'"
+ Grid.Row="2" Grid.Column="3" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="BC'"
+ Grid.Row="2" Grid.Column="4" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="DE'"
+ Grid.Row="2" Grid.Column="5" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="HL'"
+ Grid.Row="2" Grid.Column="6" />
+
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding IY, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="0"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding IY, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="1"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding SP, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="2"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding AF_, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="3"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding BC_, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="4"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding DE_, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="5"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding HL_, Mode=OneWay}"
+ Grid.Row="3" Grid.Column="6"/>
+
+ <TextBlock Style="{StaticResource StateInfo}" Text="IM"
+ Grid.Row="4" Grid.Column="0" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="I"
+ Grid.Row="4" Grid.Column="1" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="R"
+ Grid.Row="4" Grid.Column="2" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="IFF1"
+ Grid.Row="4" Grid.Column="3" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="IFF2"
+ Grid.Row="4" Grid.Column="4" />
+ <TextBlock Style="{StaticResource StateInfo}" Text="Executed Instructions"
+ Grid.Row="4" Grid.Column="5" Grid.ColumnSpan="2"/>
+
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding IM, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="0"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding I, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="1"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding R, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="2"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding IFF1, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="3"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding IFF2, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="4"/>
+ <TextBlock Style="{StaticResource StateData}"
+ Text="{Binding ExecutedInstructions, Mode=OneWay}"
+ Grid.Row="5" Grid.Column="5" Grid.ColumnSpan="2"/>
+
+ </Grid>
+
+ <!-- Disassembly -->
+ <ListBox x:Name="AsmDisplay" Grid.ColumnSpan="2" Grid.Row="1"
+ ItemsSource="{Binding Disassembly, Mode=OneWay}"
+ VerticalAlignment="Top"
+ FontFamily="Courier New"/>
+
+ <!-- Step -->
+ <Button Height="100"
+ Content="{Binding DisassemblerStepButtonText, Source={StaticResource Strings}}"
+ Grid.Row="2" Grid.Column="0"
+ FontSize="18"
+ Click="StepClick" />
+
+ <!-- Run Frame -->
+ <Button Height="100"
+ Content="{Binding DisassemblerRunFrameButtonText, Source={StaticResource Strings}}"
+ Grid.Row="2" Grid.Column="1"
+ FontSize="18"
+ Click="RunClick" />
+ </Grid>
+ </Grid>
+
+</phone:PhoneApplicationPage>
diff --git a/WPZX81/WPZX81/DisassemblerPage.xaml.cs b/WPZX81/WPZX81/DisassemblerPage.xaml.cs
new file mode 100644
index 0000000..f5b1aa5
--- /dev/null
+++ b/WPZX81/WPZX81/DisassemblerPage.xaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using Microsoft.Phone.Controls;
+
+namespace WPZX81
+{
+ /// <summary>
+ /// Displays the disassembler page. Not even attempted to MVVM it.
+ /// </summary>
+ public partial class DisassemblerPage : PhoneApplicationPage, INotifyPropertyChanged
+ {
+ private DisassemblerViewModel model;
+
+ public DisassemblerPage()
+ {
+ model = new DisassemblerViewModel();
+ DataContext = model;
+ InitializeComponent();
+ }
+
+ private void StepClick(object sender, RoutedEventArgs e)
+ {
+ model.Step();
+ }
+
+ private void RunClick(object sender, RoutedEventArgs e)
+ {
+ model.Run();
+ }
+
+ #region INotifyPropertyChanged Members
+
+ /// <summary>
+ /// Event for property changes.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/WPZX81/WPZX81/DisassemblerViewModel.cs b/WPZX81/WPZX81/DisassemblerViewModel.cs
new file mode 100644
index 0000000..b0ff2f7
--- /dev/null
+++ b/WPZX81/WPZX81/DisassemblerViewModel.cs
@@ -0,0 +1,258 @@
+using System;
+using System.Net;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Ink;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+using Noddybox.Emulation.EightBit.Z80;
+using System.Collections.Generic;
+
+namespace WPZX81
+{
+ /// <summary>
+ /// Implements a view model for the diassembler page.
+ /// </summary>
+ public class DisassemblerViewModel : BaseViewModel
+ {
+ #region Private data
+
+ private Z80Cpu z80;
+ private int a;
+ private string flags;
+ private int bc;
+ private int de;
+ private int hl;
+ private int af_;
+ private int bc_;
+ private int de_;
+ private int hl_;
+ private int ix;
+ private int iy;
+ private int sp;
+ private int pc;
+ private int i;
+ private int r;
+ private int im;
+ private string iff1;
+ private string iff2;
+ private uint executedInstructions;
+
+ #endregion
+
+ #region Private methods
+
+ private void Update()
+ {
+ Z80Cpu z80 = Shared.ZX81.Z80;
+
+ A = z80.Acummulator;
+ BC = z80.BC_Register.reg;
+ DE = z80.DE_Register.reg;
+ HL = z80.HL_Register.reg;
+ IX = z80.IX_Register.reg;
+ IY = z80.IY_Register.reg;
+ AF_ = z80.AF_Alternate.reg;
+ BC_ = z80.BC_Alternate.reg;
+ DE_ = z80.DE_Alternate.reg;
+ HL_ = z80.HL_Alternate.reg;
+ PC = z80.ProgramCounter;
+ SP = z80.StackPointer;
+ ExecutedInstructions = z80.ExecutedInstructions;
+ I = z80.InterruptVector;
+ R = z80.Refresh;
+ IFF1 = z80.IFF1_Register ? "ON":"OFF";
+ IFF2 = z80.IFF2_Register ? "ON":"OFF";
+
+ char[] names = new char[8] {'C', 'N', 'P', '3', 'H', '5', 'Z', 'S'};
+ char[] flags = new char[8];
+ int f;
+
+ for(f = 0; f < 8; f++)
+ {
+ if (((int)z80.StatusFlags & (1 << f)) == (1 << f))
+ {
+ flags[7-f] = names[7-f];
+ }
+ else
+ {
+ flags[7-f] = '-';
+ }
+ }
+
+ Flags = new String(flags);
+ }
+
+ #endregion
+
+ #region Properties
+
+ public int A
+ {
+ get {return a;}
+ set {SetValue(ref a, value, "A");}
+ }
+
+ public string Flags
+ {
+ get {return flags;}
+ set {SetValue(ref flags, value, "Flags");}
+ }
+
+ public int BC
+ {
+ get {return bc;}
+ set {SetValue(ref bc, value, "BC");}
+ }
+
+ public int DE
+ {
+ get {return de;}
+ set {SetValue(ref de, value, "DE");}
+ }
+
+ public int HL
+ {
+ get {return hl;}
+ set {SetValue(ref hl, value, "HL");}
+ }
+
+ public int AF_
+ {
+ get {return af_;}
+ set {SetValue(ref af_, value, "AF_");}
+ }
+
+ public int BC_
+ {
+ get {return bc_;}
+ set {SetValue(ref bc_, value, "BC_");}
+ }
+
+ public int DE_
+ {
+ get {return de_;}
+ set {SetValue(ref de_, value, "DE_");}
+ }
+
+ public int HL_
+ {
+ get {return hl_;}
+ set {SetValue(ref hl_, value, "HL_");}
+ }
+
+ public int IX
+ {
+ get {return ix;}
+ set {SetValue(ref ix, value, "IX");}
+ }
+
+ public int IY
+ {
+ get {return iy;}
+ set {SetValue(ref iy, value, "IY");}
+ }
+
+ public int SP
+ {
+ get {return sp;}
+ set {SetValue(ref sp, value, "SP");}
+ }
+
+ public int PC
+ {
+ get {return pc;}
+ set {SetValue(ref pc, value, "PC", "Disassembly");}
+ }
+
+ public uint ExecutedInstructions
+ {
+ get {return executedInstructions;}
+ set {SetValue(ref executedInstructions, value, "ExecutedInstructions");}
+ }
+
+ public int I
+ {
+ get {return i;}
+ set {SetValue(ref i, value, "I");}
+ }
+
+ public int R
+ {
+ get {return r;}
+ set {SetValue(ref r, value, "R");}
+ }
+ public int IM
+ {
+ get {return im;}
+ set {SetValue(ref im, value, "IM");}
+ }
+ public string IFF1
+ {
+ get {return iff1;}
+ set {SetValue(ref iff1, value, "ExecutedInstructions");}
+ }
+ public string IFF2
+ {
+ get {return iff2;}
+ set {SetValue(ref iff2, value, "ExecutedInstructions");}
+ }
+
+ public IEnumerable<DisassemblerLine> Disassembly
+ {
+ get
+ {
+ List<DisassemblerLine> list = new List<DisassemblerLine>();
+
+ ushort pc = Shared.ZX81.Z80.ProgramCounter;
+ string address;
+ string opcode;
+ string hexdump;
+
+ for(int f = 0 ; f < 15; f++)
+ {
+ pc = Shared.ZX81.Disassembler.Disassemble(pc, out address, out opcode, out hexdump);
+ list.Add(new DisassemblerLine() {Address = address, Opcode = opcode, Hexdump = hexdump});
+ }
+
+ return list;
+ }
+ }
+
+ #endregion
+
+ #region Public methods
+
+ /// <summary>
+ /// Run the ZX81 for a step.
+ /// </summary>
+ public void Step()
+ {
+ Shared.ZX81.Step();
+ Update();
+ }
+
+ /// <summary>
+ /// Run the ZX81 for a frame.
+ /// </summary>
+ public void Run()
+ {
+ Shared.ZX81.Run();
+ Update();
+ }
+
+ #endregion
+
+ #region Constructors
+
+ public DisassemblerViewModel()
+ {
+ Update();
+ }
+
+ #endregion
+ }
+}
diff --git a/WPZX81/WPZX81/MainPage.xaml b/WPZX81/WPZX81/MainPage.xaml
index 40dfc58..caa591c 100644
--- a/WPZX81/WPZX81/MainPage.xaml
+++ b/WPZX81/WPZX81/MainPage.xaml
@@ -56,10 +56,10 @@
</Button>
<!-- Open Remote Tape -->
<Button Height="100"
- Content="{Binding OpenRemotePFileButtonText, Source={StaticResource Strings}}"
+ Content="{Binding DisassemblerButtonText, Source={StaticResource Strings}}"
Grid.Row="0" Grid.Column="1"
FontSize="18"
- Click="OpenRemotePFileClick" />
+ Click="OpenDisassemblerClick" />
<!-- Open Local Tape -->
<Button Height="100"
Content="{Binding OpenGameStateButtonText, Source={StaticResource Strings}}"
diff --git a/WPZX81/WPZX81/MainPage.xaml.cs b/WPZX81/WPZX81/MainPage.xaml.cs
index 0d7dba6..940f05c 100644
--- a/WPZX81/WPZX81/MainPage.xaml.cs
+++ b/WPZX81/WPZX81/MainPage.xaml.cs
@@ -26,9 +26,9 @@ namespace WPZX81
NavigationService.Navigate(new Uri("/GamePage.xaml", UriKind.Relative));
}
- private void OpenRemotePFileClick(object sender, RoutedEventArgs e)
+ private void OpenDisassemblerClick(object sender, RoutedEventArgs e)
{
-
+ NavigationService.Navigate(new Uri("/DisassemblerPage.xaml", UriKind.Relative));
}
private void OpenGameStateClick(object sender, RoutedEventArgs e)
diff --git a/WPZX81/WPZX81/Resources/Strings.Designer.cs b/WPZX81/WPZX81/Resources/Strings.Designer.cs
index a6bb352..b245b13 100644
--- a/WPZX81/WPZX81/Resources/Strings.Designer.cs
+++ b/WPZX81/WPZX81/Resources/Strings.Designer.cs
@@ -110,6 +110,51 @@ namespace WPZX81.Resources {
}
/// <summary>
+ /// Looks up a localized string similar to Disassembler.
+ /// </summary>
+ public static string DisassemblerButtonText {
+ get {
+ return ResourceManager.GetString("DisassemblerButtonText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Disassembler.
+ /// </summary>
+ public static string DisassemblerPageTitle {
+ get {
+ return ResourceManager.GetString("DisassemblerPageTitle", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Run for a frame.
+ /// </summary>
+ public static string DisassemblerRunFrameButtonText {
+ get {
+ return ResourceManager.GetString("DisassemblerRunFrameButtonText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Step.
+ /// </summary>
+ public static string DisassemblerStepButtonText {
+ get {
+ return ResourceManager.GetString("DisassemblerStepButtonText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Z80 State.
+ /// </summary>
+ public static string DisassemblerZ80Text {
+ get {
+ return ResourceManager.GetString("DisassemblerZ80Text", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to See the GNU General Public License Online.
/// </summary>
public static string LicenseHyperlinkText {
@@ -164,24 +209,6 @@ namespace WPZX81.Resources {
}
/// <summary>
- /// Looks up a localized string similar to Load Remote .P file.
- /// </summary>
- public static string OpenRemotePFileButtonText {
- get {
- return ResourceManager.GetString("OpenRemotePFileButtonText", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Load Remote .P file.
- /// </summary>
- public static string OpenRemotePFilePageTitle {
- get {
- return ResourceManager.GetString("OpenRemotePFilePageTitle", resourceCulture);
- }
- }
-
- /// <summary>
/// Looks up a localized string similar to 16K RAM Pack Inserted.
/// </summary>
public static string RamPackText {
diff --git a/WPZX81/WPZX81/Resources/Strings.resx b/WPZX81/WPZX81/Resources/Strings.resx
index c892b78..9880707 100644
--- a/WPZX81/WPZX81/Resources/Strings.resx
+++ b/WPZX81/WPZX81/Resources/Strings.resx
@@ -154,11 +154,11 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
<data name="OpenGameStatePageTitle" xml:space="preserve">
<value>Load Game</value>
</data>
- <data name="OpenRemotePFileButtonText" xml:space="preserve">
- <value>Load Remote .P file</value>
+ <data name="DisassemblerButtonText" xml:space="preserve">
+ <value>Disassembler</value>
</data>
- <data name="OpenRemotePFilePageTitle" xml:space="preserve">
- <value>Load Remote .P file</value>
+ <data name="DisassemblerPageTitle" xml:space="preserve">
+ <value>Disassembler</value>
</data>
<data name="ROMCopyrightHyperlinkText" xml:space="preserve">
<value>Nine Tiles Network Ltd.</value>
@@ -211,4 +211,13 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
<data name="RamPackText" xml:space="preserve">
<value>16K RAM Pack Inserted</value>
</data>
+ <data name="DisassemblerRunFrameButtonText" xml:space="preserve">
+ <value>Run for a frame</value>
+ </data>
+ <data name="DisassemblerStepButtonText" xml:space="preserve">
+ <value>Step</value>
+ </data>
+ <data name="DisassemblerZ80Text" xml:space="preserve">
+ <value>Z80 State</value>
+ </data>
</root> \ No newline at end of file
diff --git a/WPZX81/WPZX81/WPZX81.csproj b/WPZX81/WPZX81/WPZX81.csproj
index 8e80b73..9c8122c 100644
--- a/WPZX81/WPZX81/WPZX81.csproj
+++ b/WPZX81/WPZX81/WPZX81.csproj
@@ -69,6 +69,12 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
+ <Compile Include="BaseViewModel.cs" />
+ <Compile Include="DisassemblerLine.cs" />
+ <Compile Include="DisassemblerPage.xaml.cs">
+ <DependentUpon>DisassemblerPage.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="DisassemblerViewModel.cs" />
<Compile Include="GamePage.xaml.cs">
<DependentUpon>GamePage.xaml</DependentUpon>
</Compile>
@@ -98,6 +104,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="DisassemblerPage.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="GamePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -126,6 +136,10 @@
<Content Include="SplashScreenImage.jpg" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\..\Noddybox.Emulation\WindowsPhone\Noddybox.Emulation.EightBit.Z80.Disassembler\Noddybox.Emulation.EightBit.Z80.Disassembler.csproj">
+ <Project>{08D7120E-3D84-49D2-B73D-255E5DB9655C}</Project>
+ <Name>Noddybox.Emulation.EightBit.Z80.Disassembler</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\..\Noddybox.Emulation\WindowsPhone\Noddybox.Emulation.EightBit.Z80\Noddybox.Emulation.EightBit.Z80.csproj">
<Project>{7F257886-40D3-4E2A-BA9C-C5FEE93C08E9}</Project>
<Name>Noddybox.Emulation.EightBit.Z80</Name>
diff --git a/WPZX81/WPZX81/ZX81/Emulation.cs b/WPZX81/WPZX81/ZX81/Emulation.cs
index 7e6bbbf..d328e72 100644
--- a/WPZX81/WPZX81/ZX81/Emulation.cs
+++ b/WPZX81/WPZX81/ZX81/Emulation.cs
@@ -6,6 +6,7 @@ using Microsoft.Xna.Framework.Graphics;
using System.Windows.Resources;
using Microsoft.Xna.Framework;
using System.Diagnostics;
+using Noddybox.Emulation.EightBit.Z80.Disassembler;
namespace WPZX81.ZX81
{
@@ -18,7 +19,6 @@ namespace WPZX81.ZX81
private Clock clock;
private byte[] mem;
- private Z80Cpu z80;
private bool fast;
private bool started;
private bool waitkey;
@@ -123,7 +123,7 @@ namespace WPZX81.ZX81
ushort[] data = new ushort[64];
Register16 addr = new Register16(0);
- addr.high = z80.InterruptVector;
+ addr.high = Z80.InterruptVector;
Debug.WriteLine("Loading font from 0x{0:X4}", addr.reg);
@@ -303,25 +303,39 @@ namespace WPZX81.ZX81
}
}
- if (lastk1 > 0 && (lastk1 != prev_last_key1 ||
- lastk2 != prev_last_key2))
- {
- mem[CDFLAG] |= 1;
- }
- else
- {
- mem[CDFLAG] &= 0xfe;
- }
-
- mem[LASTK1] = (byte)(lastk1^0xff);
- mem[LASTK2] = (byte)(lastk2^0xff);
-
- prev_last_key1 = lastk1;
- prev_last_key2 = lastk2;
+ if (lastk1 > 0 && (lastk1 != prev_last_key1 ||
+ lastk2 != prev_last_key2))
+ {
+ mem[CDFLAG] |= 1;
+ }
+ else
+ {
+ mem[CDFLAG] &= 0xfe;
+ }
+
+ mem[LASTK1] = (byte)(lastk1^0xff);
+ mem[LASTK2] = (byte)(lastk2^0xff);
+
+ prev_last_key1 = lastk1;
+ prev_last_key2 = lastk2;
}
#endregion
+ #region Public Properties
+
+ /// <summary>
+ /// The Z80 CPU being used.
+ /// </summary>
+ public Z80Cpu Z80 {private set; get;}
+
+ /// <summary>
+ /// A disassembler for this machine.
+ /// </summary>
+ public Z80Disassembler Disassembler {private set; get;}
+
+ #endregion
+
#region Public methods
/// <summary>
@@ -331,29 +345,49 @@ namespace WPZX81.ZX81
{
Stopwatch s = Stopwatch.StartNew();
- z80.ExecutedInstructions = 0;
+ Z80.ExecutedInstructions = 0;
if (fast)
{
clock.StartFrame();
- z80.Run();
+ Z80.Run();
clock.StartFrame();
- z80.Run();
+ Z80.Run();
clock.StartFrame();
- z80.Run();
+ Z80.Run();
}
clock.StartFrame();
- z80.Run();
- z80.MaskableInterrupt(0);
+ Z80.Run();
+ Z80.MaskableInterrupt(0);
- if (z80.StackPointer < 0x8000)
+ if (Z80.StackPointer < 0x8000)
{
Housekeeping();
}
s.Stop();
- Debug.WriteLine("*** RUN {0} msec {1} ticks (PC = 0x{2:X4}, opcodes = {3})", s.ElapsedMilliseconds, s.ElapsedTicks, z80.ProgramCounter, z80.ExecutedInstructions);
+ Debug.WriteLine("*** RUN {0} msec {1} ticks (PC = 0x{2:X4}, opcodes = {3})", s.ElapsedMilliseconds, s.ElapsedTicks, Z80.ProgramCounter, Z80.ExecutedInstructions);
+ }
+
+ /// <summary>
+ /// Run the emulation for a step.
+ /// </summary>
+ public void Step()
+ {
+ Z80.Step();
+
+ if (clock.FrameDone)
+ {
+ clock.StartFrame();
+ Z80.ExecutedInstructions = 0;
+ Z80.MaskableInterrupt(0);
+
+ if (Z80.StackPointer < 0x8000)
+ {
+ Housekeeping();
+ }
+ }
}
/// <summary>
@@ -366,10 +400,10 @@ namespace WPZX81.ZX81
// Check if character pointer has updated
//
- if (z80.InterruptVector != lastI)
+ if (Z80.InterruptVector != lastI)
{
LoadFont();
- lastI = z80.InterruptVector;
+ lastI = Z80.InterruptVector;
}
// Update display
@@ -460,7 +494,7 @@ namespace WPZX81.ZX81
PatchROM();
clock.Reset();
- z80.Reset();
+ Z80.Reset();
}
#endregion
@@ -473,9 +507,11 @@ namespace WPZX81.ZX81
matrix = new byte[8];
mem = new byte[0x10000];
clock = new Clock(16000 * 2, 50);
- z80 = new Z80Cpu();
- z80.Initialise(this, this, clock);
- z80.EDNopEvent += EDCallback;
+ Z80 = new Z80Cpu();
+ Z80.Initialise(this, this, clock);
+ Z80.EDNopEvent += EDCallback;
+ Disassembler = new Z80Disassembler();
+ Disassembler.Initialise(this);
Reset();
}