summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2012-05-16 23:10:07 +0000
committerIan C <ianc@noddybox.co.uk>2012-05-16 23:10:07 +0000
commit5471e2656a56bf99ea9053d4bc479f1d3ba998e9 (patch)
tree38a5f61c1b09d5bfd4227774108f964eb949c581
parent097e255e9d87ebbb2d1f93aa564d74aeba39a5d4 (diff)
Added page to display tape contents. Also fixed bug in tape block length handling on the Spectrum.
-rw-r--r--wpspec/wpspec/Converters/ConvertCamelToHuman.cs46
-rw-r--r--wpspec/wpspec/DisplayTapePage.xaml126
-rw-r--r--wpspec/wpspec/DisplayTapePage.xaml.cs24
-rw-r--r--wpspec/wpspec/Resources/Strings.Designer.cs9
-rw-r--r--wpspec/wpspec/Resources/Strings.resx3
-rw-r--r--wpspec/wpspec/Spectrum/Emulation.cs8
-rw-r--r--wpspec/wpspec/Spectrum/Tape.cs26
-rw-r--r--wpspec/wpspec/Spectrum/TapeBlock.cs154
-rw-r--r--wpspec/wpspec/wpspec.csproj9
9 files changed, 401 insertions, 4 deletions
diff --git a/wpspec/wpspec/Converters/ConvertCamelToHuman.cs b/wpspec/wpspec/Converters/ConvertCamelToHuman.cs
new file mode 100644
index 0000000..3d9f5c6
--- /dev/null
+++ b/wpspec/wpspec/Converters/ConvertCamelToHuman.cs
@@ -0,0 +1,46 @@
+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 System.Windows.Data;
+
+namespace wpspec.Converters
+{
+ /// <summary>
+ /// Convert a "CamelCaseString" to "Camel Case String".
+ /// </summary>
+ public class ConvertCamelToHuman : IValueConverter
+ {
+ #region IValueConverter Members
+
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ string s = String.Empty;
+
+ foreach (char c in value.ToString())
+ {
+ if (Char.IsUpper(c) && s.Length > 0)
+ {
+ s += " ";
+ }
+
+ s += c;
+ }
+
+ return s;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/wpspec/wpspec/DisplayTapePage.xaml b/wpspec/wpspec/DisplayTapePage.xaml
new file mode 100644
index 0000000..c9baf32
--- /dev/null
+++ b/wpspec/wpspec/DisplayTapePage.xaml
@@ -0,0 +1,126 @@
+<phone:PhoneApplicationPage
+ x:Class="wpspec.DisplayTapePage"
+ 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:wpspec.Resources"
+ xmlns:conv="clr-namespace:wpspec.Converters"
+ 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" />
+ <conv:ConvertIntToHex4 x:Key="ConvertIntToHex4" />
+ <conv:ConvertCamelToHuman x:Key="ConvertCamelToHuman" />
+
+ <Style x:Name="TapeText" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Arial" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="FontSize" Value="12" />
+ <Setter Property="HorizontalAlignment" Value="Left" />
+ </Style>
+
+ <Style x:Name="TapeHeader" TargetType="TextBlock">
+ <Setter Property="FontFamily" Value="Arial" />
+ <Setter Property="FontWeight" Value="Normal" />
+ <Setter Property="FontSize" Value="12" />
+ <Setter Property="HorizontalAlignment" Value="Left" />
+ <Setter Property="TextWrapping" Value="Wrap" />
+ </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 DisplayTapeTitleText, 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="*" />
+ </Grid.RowDefinitions>
+ <Grid Background="DarkSlateBlue">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="150" />
+ <ColumnDefinition Width="100" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ </Grid.ColumnDefinitions>
+ <TextBlock Text="Type" Grid.Column="0"
+ Style="{StaticResource TapeHeader}" />
+ <TextBlock Text="Filename" Grid.Column="1"
+ Style="{StaticResource TapeHeader}" />
+ <TextBlock Text="Tape Block Length"
+ Grid.Column="2"
+ Style="{StaticResource TapeHeader}" />
+ <TextBlock Text="Start Address" Grid.Column="3"
+ Style="{StaticResource TapeHeader}" />
+ <TextBlock Text="Length" Grid.Column="4"
+ Style="{StaticResource TapeHeader}" />
+ <TextBlock Text="CRC Valid" Grid.Column="5"
+ Style="{StaticResource TapeHeader}" />
+ </Grid>
+ <ListBox Grid.Row="1"
+ ItemsSource="{Binding TapeBlocks, Mode=OneWay}"
+ VerticalAlignment="Top">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="150" />
+ <ColumnDefinition Width="100" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ <ColumnDefinition Width="50" />
+ </Grid.ColumnDefinitions>
+ <TextBlock Text="{Binding Path=TapeBlockType, Converter={StaticResource ConvertCamelToHuman}}"
+ Grid.Column="0"
+ Style="{StaticResource TapeText}" />
+ <TextBlock Text="{Binding Path=Name}"
+ Grid.Column="1"
+ Style="{StaticResource TapeText}" />
+ <TextBlock Text="{Binding Path=Length, Converter={StaticResource ConvertIntToHex4}}"
+ Grid.Column="2"
+ Style="{StaticResource TapeText}" />
+ <TextBlock Text="{Binding Path=StartAddress, Converter={StaticResource ConvertIntToHex4}}"
+ Grid.Column="3"
+ Style="{StaticResource TapeText}" />
+ <TextBlock Text="{Binding Path=DataLength, Converter={StaticResource ConvertIntToHex4}}"
+ Grid.Column="4"
+ Style="{StaticResource TapeText}" />
+ <TextBlock Text="{Binding Path=ValidCRC}"
+ Grid.Column="5"
+ Style="{StaticResource TapeText}" />
+ </Grid>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </Grid>
+ </Grid>
+
+</phone:PhoneApplicationPage>
diff --git a/wpspec/wpspec/DisplayTapePage.xaml.cs b/wpspec/wpspec/DisplayTapePage.xaml.cs
new file mode 100644
index 0000000..ad63dd0
--- /dev/null
+++ b/wpspec/wpspec/DisplayTapePage.xaml.cs
@@ -0,0 +1,24 @@
+using System;
+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 wpspec
+{
+ public partial class DisplayTapePage : PhoneApplicationPage
+ {
+ public DisplayTapePage()
+ {
+ InitializeComponent();
+ DataContext = Shared.Spectrum.Tape;
+ }
+ }
+} \ No newline at end of file
diff --git a/wpspec/wpspec/Resources/Strings.Designer.cs b/wpspec/wpspec/Resources/Strings.Designer.cs
index 80e2336..36ad103 100644
--- a/wpspec/wpspec/Resources/Strings.Designer.cs
+++ b/wpspec/wpspec/Resources/Strings.Designer.cs
@@ -164,6 +164,15 @@ namespace wpspec.Resources {
}
/// <summary>
+ /// Looks up a localized string similar to Tape Contents.
+ /// </summary>
+ public static string DisplayTapeTitleText {
+ get {
+ return ResourceManager.GetString("DisplayTapeTitleText", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to See the GNU General Public License Online.
/// </summary>
public static string LicenseHyperlinkText {
diff --git a/wpspec/wpspec/Resources/Strings.resx b/wpspec/wpspec/Resources/Strings.resx
index 413a2f4..fab77d2 100644
--- a/wpspec/wpspec/Resources/Strings.resx
+++ b/wpspec/wpspec/Resources/Strings.resx
@@ -247,4 +247,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
<data name="PokeMemoryButtonText" xml:space="preserve">
<value>Poke Memory</value>
</data>
+ <data name="DisplayTapeTitleText" xml:space="preserve">
+ <value>Tape Contents</value>
+ </data>
</root> \ No newline at end of file
diff --git a/wpspec/wpspec/Spectrum/Emulation.cs b/wpspec/wpspec/Spectrum/Emulation.cs
index 97cbc43..d832f53 100644
--- a/wpspec/wpspec/Spectrum/Emulation.cs
+++ b/wpspec/wpspec/Spectrum/Emulation.cs
@@ -245,6 +245,10 @@ namespace wpspec.Spectrum
type = Tape.Read();
csum = id;
+ // Knock off data block type
+ //
+ block_len--;
+
// Found the requested block?
//
if (id == type)
@@ -252,10 +256,6 @@ namespace wpspec.Spectrum
byte b = 0;
byte tape_csum;
- // Knock off data block type
- //
- block_len--;
-
while(block_len > 0 && len.reg > 0)
{
b = Tape.Read();
diff --git a/wpspec/wpspec/Spectrum/Tape.cs b/wpspec/wpspec/Spectrum/Tape.cs
index 81c183a..440522a 100644
--- a/wpspec/wpspec/Spectrum/Tape.cs
+++ b/wpspec/wpspec/Spectrum/Tape.cs
@@ -8,6 +8,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
+using System.Collections.Generic;
namespace wpspec.Spectrum
{
@@ -51,6 +52,31 @@ namespace wpspec.Spectrum
}
/// <summary>
+ /// Get a list of the blocks on the tape.
+ /// </summary>
+ public List<TapeBlock> TapeBlocks
+ {
+ get
+ {
+ List<TapeBlock> l = new List<TapeBlock>();
+ int i = 0;
+ int len;
+
+ while (i < tape.Length - 2)
+ {
+ len = tape[i++];
+ len += tape[i++] * 256;
+
+ l.Add(new TapeBlock(tape, i, len));
+
+ i += len;
+ }
+
+ return l;
+ }
+ }
+
+ /// <summary>
/// Constructs a tape.
/// </summary>
/// <param name="tape">The memory block holding the tape.</param>
diff --git a/wpspec/wpspec/Spectrum/TapeBlock.cs b/wpspec/wpspec/Spectrum/TapeBlock.cs
new file mode 100644
index 0000000..36ddd95
--- /dev/null
+++ b/wpspec/wpspec/Spectrum/TapeBlock.cs
@@ -0,0 +1,154 @@
+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 wpspec.Spectrum
+{
+ /// <summary>
+ /// Represents the type of tape blocks available.
+ /// </summary>
+ public enum BlockType
+ {
+ ProgramHeader = 0, // These values match the values in the tape blocks.
+ NumericArrayHeader = 1,
+ StringArrayHeader = 2,
+ MemoryBlockHeader = 3,
+ RomDataBlock,
+ CustomDataBlock,
+ Fragment,
+ NotEnoughTape
+ };
+
+ /// <summary>
+ /// Represents a block on the tape.
+ /// </summary>
+ public class TapeBlock
+ {
+ /// <summary>
+ /// The type of the tape block.
+ /// </summary>
+ public BlockType TapeBlockType {get; private set;}
+
+ /// <summary>
+ /// The filename (if any) from a header.
+ /// </summary>
+ public string Name {get; private set;}
+
+ /// <summary>
+ /// The length of the tape block.
+ /// </summary>
+ public int? Length {get; private set;}
+
+ /// <summary>
+ /// The start address from a header.
+ /// </summary>
+ public int? StartAddress {get; private set;}
+
+ /// <summary>
+ /// The data length from a header.
+ /// </summary>
+ public int? DataLength {get; private set;}
+
+ /// <summary>
+ /// Whether the CRC was valid.
+ /// </summary>
+ public bool? ValidCRC {get; private set;}
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="tape">Memory holding the entire tape.</param>
+ /// <param name="offset">The offset of the first byte of a block.</param>
+ /// <param name="length">The length of the block.</param>
+ public TapeBlock(byte[] tape, int offset, int length)
+ {
+ // Check for enough tape
+ //
+ if (offset + length > tape.Length)
+ {
+ TapeBlockType = BlockType.NotEnoughTape;
+ }
+ else
+ {
+ // Set CRC and length
+ //
+ CheckCRC(tape, offset, length);
+
+ Length = length;
+
+ // Check for fragments
+ //
+ if (length < 2)
+ {
+ TapeBlockType = BlockType.Fragment;
+ }
+ else
+ {
+ // Check for ROM data blocks
+ //
+ if (tape[offset] == 0xff)
+ {
+ TapeBlockType = BlockType.RomDataBlock;
+ }
+ else if (tape[offset] == 0)
+ {
+ // If the first byte is zero it's perhaps a normal header block. If not, we assume a custom data block.
+ //
+ if (tape[offset + 1] < 4)
+ {
+ TapeBlockType = (BlockType)tape[offset + 1];
+
+ string fn = String.Empty;
+
+ for(int o = 2; o < 12; o++)
+ {
+ fn += (char)tape[offset + o];
+ }
+
+ Name = fn;
+
+ DataLength = tape[offset + 12];
+ DataLength += tape[offset + 13] * 256;
+
+ if (TapeBlockType == BlockType.ProgramHeader || TapeBlockType == BlockType.MemoryBlockHeader)
+ {
+ StartAddress = tape[offset + 14];
+ StartAddress += tape[offset + 15] * 256;
+ }
+ }
+ else
+ {
+ TapeBlockType = BlockType.CustomDataBlock;
+ }
+ }
+ else
+ {
+ // It's a custom data block
+ //
+ TapeBlockType = BlockType.CustomDataBlock;
+ }
+ }
+ }
+ }
+
+ private void CheckCRC(byte[] tape, int offset, int length)
+ {
+ byte crc = tape[offset++];
+ length -= 2;
+
+ while(length-- > 0)
+ {
+ crc ^= tape[offset++];
+ }
+
+ ValidCRC = (crc == tape[offset]);
+ }
+ }
+}
diff --git a/wpspec/wpspec/wpspec.csproj b/wpspec/wpspec/wpspec.csproj
index b1706b5..870d5c3 100644
--- a/wpspec/wpspec/wpspec.csproj
+++ b/wpspec/wpspec/wpspec.csproj
@@ -73,6 +73,7 @@
<DependentUpon>GamePage.xaml</DependentUpon>
</Compile>
<Compile Include="Converters\ConvertBooleanToVisibility.cs" />
+ <Compile Include="Converters\ConvertCamelToHuman.cs" />
<Compile Include="Converters\ConvertFlagsToString.cs" />
<Compile Include="Converters\ConvertIntToHex2.cs" />
<Compile Include="Converters\ConvertIntToHex4.cs" />
@@ -82,6 +83,9 @@
<Compile Include="DisplayKeyboardPage.xaml.cs">
<DependentUpon>DisplayKeyboardPage.xaml</DependentUpon>
</Compile>
+ <Compile Include="DisplayTapePage.xaml.cs">
+ <DependentUpon>DisplayTapePage.xaml</DependentUpon>
+ </Compile>
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
@@ -112,6 +116,7 @@
<Compile Include="Spectrum\Emulation.cs" />
<Compile Include="Spectrum\SpectrumKeySymbol.cs" />
<Compile Include="Spectrum\Tape.cs" />
+ <Compile Include="Spectrum\TapeBlock.cs" />
<Compile Include="UtilsPage.xaml.cs">
<DependentUpon>UtilsPage.xaml</DependentUpon>
</Compile>
@@ -137,6 +142,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="DisplayTapePage.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="MainPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>