From 5471e2656a56bf99ea9053d4bc479f1d3ba998e9 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 16 May 2012 23:10:07 +0000 Subject: Added page to display tape contents. Also fixed bug in tape block length handling on the Spectrum. --- wpspec/wpspec/Converters/ConvertCamelToHuman.cs | 46 +++++++ wpspec/wpspec/DisplayTapePage.xaml | 126 +++++++++++++++++++ wpspec/wpspec/DisplayTapePage.xaml.cs | 24 ++++ wpspec/wpspec/Resources/Strings.Designer.cs | 9 ++ wpspec/wpspec/Resources/Strings.resx | 3 + wpspec/wpspec/Spectrum/Emulation.cs | 8 +- wpspec/wpspec/Spectrum/Tape.cs | 26 ++++ wpspec/wpspec/Spectrum/TapeBlock.cs | 154 ++++++++++++++++++++++++ wpspec/wpspec/wpspec.csproj | 9 ++ 9 files changed, 401 insertions(+), 4 deletions(-) create mode 100644 wpspec/wpspec/Converters/ConvertCamelToHuman.cs create mode 100644 wpspec/wpspec/DisplayTapePage.xaml create mode 100644 wpspec/wpspec/DisplayTapePage.xaml.cs create mode 100644 wpspec/wpspec/Spectrum/TapeBlock.cs 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 +{ + /// + /// Convert a "CamelCaseString" to "Camel Case String". + /// + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ -163,6 +163,15 @@ namespace wpspec.Resources { } } + /// + /// Looks up a localized string similar to Tape Contents. + /// + public static string DisplayTapeTitleText { + get { + return ResourceManager.GetString("DisplayTapeTitleText", resourceCulture); + } + } + /// /// Looks up a localized string similar to See the GNU General Public License Online. /// 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 Poke Memory + + Tape Contents + \ 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 { @@ -50,6 +51,31 @@ namespace wpspec.Spectrum return c1+(c2<<8); } + /// + /// Get a list of the blocks on the tape. + /// + public List TapeBlocks + { + get + { + List l = new List(); + 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; + } + } + /// /// Constructs a tape. /// 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 +{ + /// + /// Represents the type of tape blocks available. + /// + public enum BlockType + { + ProgramHeader = 0, // These values match the values in the tape blocks. + NumericArrayHeader = 1, + StringArrayHeader = 2, + MemoryBlockHeader = 3, + RomDataBlock, + CustomDataBlock, + Fragment, + NotEnoughTape + }; + + /// + /// Represents a block on the tape. + /// + public class TapeBlock + { + /// + /// The type of the tape block. + /// + public BlockType TapeBlockType {get; private set;} + + /// + /// The filename (if any) from a header. + /// + public string Name {get; private set;} + + /// + /// The length of the tape block. + /// + public int? Length {get; private set;} + + /// + /// The start address from a header. + /// + public int? StartAddress {get; private set;} + + /// + /// The data length from a header. + /// + public int? DataLength {get; private set;} + + /// + /// Whether the CRC was valid. + /// + public bool? ValidCRC {get; private set;} + + /// + /// Constructor. + /// + /// Memory holding the entire tape. + /// The offset of the first byte of a block. + /// The length of the block. + 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 @@ GamePage.xaml + @@ -82,6 +83,9 @@ DisplayKeyboardPage.xaml + + DisplayTapePage.xaml + MainPage.xaml @@ -112,6 +116,7 @@ + UtilsPage.xaml @@ -137,6 +142,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile -- cgit v1.2.3