diff --git a/Amazfit.sln b/Amazfit.sln
index 7721e16..8661403 100644
--- a/Amazfit.sln
+++ b/Amazfit.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchFace.Parser", "WatchFa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WatchFace", "WatchFace\WatchFace.csproj", "{963BCF47-8C24-4219-BC84-8EC3670205B3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Resources", "Resources\Resources.csproj", "{EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,22 @@ Global
{963BCF47-8C24-4219-BC84-8EC3670205B3}.Release|x64.Build.0 = Release|Any CPU
{963BCF47-8C24-4219-BC84-8EC3670205B3}.Release|x86.ActiveCfg = Release|Any CPU
{963BCF47-8C24-4219-BC84-8EC3670205B3}.Release|x86.Build.0 = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|ARM.Build.0 = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|x64.Build.0 = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Debug|x86.Build.0 = Debug|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|ARM.ActiveCfg = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|ARM.Build.0 = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|x64.ActiveCfg = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|x64.Build.0 = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|x86.ActiveCfg = Release|Any CPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/WatchFace.Parser/Utils/BitReader.cs b/Resources/BitReader.cs
similarity index 98%
rename from WatchFace.Parser/Utils/BitReader.cs
rename to Resources/BitReader.cs
index 34134ce..da803e3 100644
--- a/WatchFace.Parser/Utils/BitReader.cs
+++ b/Resources/BitReader.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
-namespace WatchFace.Parser.Utils
+namespace Resources
{
public class BitReader
{
diff --git a/WatchFace.Parser/ImageReader.cs b/Resources/ImageReader.cs
similarity index 93%
rename from WatchFace.Parser/ImageReader.cs
rename to Resources/ImageReader.cs
index b0cb182..03fb27b 100644
--- a/WatchFace.Parser/ImageReader.cs
+++ b/Resources/ImageReader.cs
@@ -2,9 +2,8 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
-using WatchFace.Parser.Utils;
-namespace WatchFace.Parser
+namespace Resources
{
public class ImageReader
{
@@ -26,7 +25,7 @@ namespace WatchFace.Parser
{
var signature = _reader.ReadChars(4);
if (signature[0] != 'B' || signature[1] != 'M')
- throw new ArgumentOutOfRangeException("signature", "Signature doesn't match.");
+ throw new ArgumentException("Image signature doesn't match.");
ReadHeader();
ReadPalette();
diff --git a/Resources/Properties/AssemblyInfo.cs b/Resources/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..eb4d018
--- /dev/null
+++ b/Resources/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ResourcesReader")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ResourcesReader")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("edd55d5d-9e80-451b-ac8a-0746ba6dc6e9")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Resources/Resources.csproj b/Resources/Resources.csproj
new file mode 100644
index 0000000..4095418
--- /dev/null
+++ b/Resources/Resources.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {EDD55D5D-9E80-451B-AC8A-0746BA6DC6E9}
+ Library
+ Properties
+ Resources
+ Resources
+ v4.6.1
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\NLog.4.4.12\lib\net45\NLog.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Resources/ResourcesExtractor.cs b/Resources/ResourcesExtractor.cs
new file mode 100644
index 0000000..fc3b92d
--- /dev/null
+++ b/Resources/ResourcesExtractor.cs
@@ -0,0 +1,29 @@
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using NLog;
+
+namespace Resources
+{
+ public class ResourcesExtractor
+ {
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+ private readonly Bitmap[] _images;
+
+ public ResourcesExtractor(Bitmap[] images)
+ {
+ _images = images;
+ }
+
+ public void Extract(string outputDirectory)
+ {
+ for (var i = 0; i < _images.Length; i++)
+ {
+ var fileName = Path.Combine(outputDirectory, $"{i}.bmp");
+ Logger.Debug("Exporting {0}...", fileName);
+ _images[i].Save(fileName, ImageFormat.Bmp);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Resources/ResourcesFileReader.cs b/Resources/ResourcesFileReader.cs
new file mode 100644
index 0000000..0cc4f2b
--- /dev/null
+++ b/Resources/ResourcesFileReader.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Drawing;
+using System.IO;
+using NLog;
+
+namespace Resources
+{
+ public class ResourcesFileReader
+ {
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+ private readonly BinaryReader _binaryReader;
+ private readonly Stream _stream;
+
+ public ResourcesFileReader(Stream stream)
+ {
+ _stream = stream;
+ _binaryReader = new BinaryReader(stream);
+ }
+
+ public Bitmap[] Read()
+ {
+ Logger.Trace("Reading resources header");
+ var header = ResourcesHeader.ReadFrom(_binaryReader);
+ Logger.Trace("Resources header was read:");
+ Logger.Trace("Signature: {0}, Version: {1}, ResourcesCount: {2}, IsValid: {3}",
+ header.Signature, header.Version, header.ResourcesCount, header.IsValid
+ );
+
+ if (!header.IsValid)
+ throw new ArgumentException("Invalid resources header");
+
+ return new ResourcesReader(_stream).Read(header.ResourcesCount);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Resources/ResourcesHeader.cs b/Resources/ResourcesHeader.cs
new file mode 100644
index 0000000..3a3617f
--- /dev/null
+++ b/Resources/ResourcesHeader.cs
@@ -0,0 +1,29 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Resources
+{
+ public class ResourcesHeader
+ {
+ public const int HeaderSize = 20;
+ private const string ResHeaderSignature = "HMRES";
+ private readonly byte[] _header;
+
+ public ResourcesHeader(byte[] header)
+ {
+ _header = header;
+ }
+
+ public string Signature => Encoding.ASCII.GetString(_header, 0, 5);
+ public bool IsValid => Signature == ResHeaderSignature;
+ public uint Version => _header[5];
+ public uint ResourcesCount => BitConverter.ToUInt32(_header, 16);
+
+ public static ResourcesHeader ReadFrom(BinaryReader reader)
+ {
+ var buffer = reader.ReadBytes(HeaderSize);
+ return new ResourcesHeader(buffer);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Resources/ResourcesReader.cs b/Resources/ResourcesReader.cs
new file mode 100644
index 0000000..14c5020
--- /dev/null
+++ b/Resources/ResourcesReader.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Drawing;
+using System.IO;
+using NLog;
+
+namespace Resources
+{
+ public class ResourcesReader
+ {
+ private const int OffsetTableItemLength = 4;
+ private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+
+ private readonly BinaryReader _binaryReader;
+ private readonly Stream _stream;
+
+ public ResourcesReader(Stream stream)
+ {
+ _stream = stream;
+ _binaryReader = new BinaryReader(_stream);
+ }
+
+ public Bitmap[] Read(uint imagesTableLength)
+ {
+ var offsetsTableLength = (int) (imagesTableLength * OffsetTableItemLength);
+ Logger.Trace("Reading resources offsets table with {0} elements ({1} bytes)",
+ imagesTableLength, offsetsTableLength
+ );
+ var imagesOffsets = _binaryReader.ReadBytes(offsetsTableLength);
+ var imagesOffset = _stream.Position;
+
+ Logger.Trace("Reading {0} resources", imagesTableLength);
+ var images = new Bitmap[imagesTableLength];
+ for (var i = 0; i < imagesTableLength; i++)
+ {
+ var imageOffset = BitConverter.ToUInt32(imagesOffsets, i * OffsetTableItemLength) + imagesOffset;
+ if (_stream.Position != imageOffset)
+ {
+ var bytesGap = imageOffset - _stream.Position;
+ Logger.Warn("Found {0} bytes gap before resource number {1}", bytesGap, i);
+ _stream.Seek(imageOffset, SeekOrigin.Begin);
+ }
+ images[i] = new ImageReader(_stream).Read();
+ }
+ return images;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Resources/packages.config b/Resources/packages.config
new file mode 100644
index 0000000..80757f3
--- /dev/null
+++ b/Resources/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/WatchFace.Parser/Elements/Scales.cs b/WatchFace.Parser/Elements/Scales.cs
deleted file mode 100644
index b8e2eac..0000000
--- a/WatchFace.Parser/Elements/Scales.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using WatchFace.Parser.Elements.BasicElements;
-using WatchFace.Parser.Utils;
-
-namespace WatchFace.Parser.Elements
-{
- public class Scales
- {
- [RawParameter(Id = 2)]
- public Scale LinearSteps { get; set; }
-
- [RawParameter(Id = 3)]
- public CircleScale CircleSteps { get; set; }
- }
-}
\ No newline at end of file
diff --git a/WatchFace.Parser/Elements/StepsProgress.cs b/WatchFace.Parser/Elements/StepsProgress.cs
new file mode 100644
index 0000000..c94d432
--- /dev/null
+++ b/WatchFace.Parser/Elements/StepsProgress.cs
@@ -0,0 +1,17 @@
+using WatchFace.Parser.Elements.BasicElements;
+using WatchFace.Parser.Utils;
+
+namespace WatchFace.Parser.Elements
+{
+ public class StepsProgress
+ {
+ [RawParameter(Id = 1)]
+ public Image GoalImage { get; set; }
+
+ [RawParameter(Id = 2)]
+ public Scale Linear { get; set; }
+
+ [RawParameter(Id = 3)]
+ public CircleScale Circle { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/WatchFace.Parser/Elements/WeatherElements/OneLineTemperature.cs b/WatchFace.Parser/Elements/WeatherElements/OneLineTemperature.cs
index 30954af..32c6aed 100644
--- a/WatchFace.Parser/Elements/WeatherElements/OneLineTemperature.cs
+++ b/WatchFace.Parser/Elements/WeatherElements/OneLineTemperature.cs
@@ -15,7 +15,7 @@ namespace WatchFace.Parser.Elements.WeatherElements
public long DelimiterImageIndex { get; set; }
[RawParameter(Id = 4)]
- public long Unknown4 { get; set; }
+ public long AppendDegreesForBoth { get; set; }
[RawParameter(Id = 5)]
public long DegreesImageIndex { get; set; }
diff --git a/WatchFace.Parser/Exceptions/DuplicateParameterException.cs b/WatchFace.Parser/Exceptions/DuplicateParameterException.cs
deleted file mode 100644
index 4ef5e3c..0000000
--- a/WatchFace.Parser/Exceptions/DuplicateParameterException.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using WatchFace.Models;
-
-namespace WatchFace
-{
- public class DuplicateParameterException : Exception
- {
- public DuplicateParameterException(Parameter paramter, string path) : base(
- $"Parameter with Id: {paramter.Id} was already set in this position: {path}."
- ) { }
- }
-}
\ No newline at end of file
diff --git a/WatchFace.Parser/Exceptions/InvalidParameterException.cs b/WatchFace.Parser/Exceptions/InvalidParameterException.cs
deleted file mode 100644
index ab8603d..0000000
--- a/WatchFace.Parser/Exceptions/InvalidParameterException.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using WatchFace.Parser.Models;
-
-namespace WatchFace
-{
- public class InvalidParameterException : Exception
- {
- public InvalidParameterException(Parameter paramter, string path) : base(
- $"Parameter with Id: {paramter.Id} is not supported in this position: {path}."
- ) { }
- }
-}
\ No newline at end of file
diff --git a/WatchFace.Parser/Reader.cs b/WatchFace.Parser/Reader.cs
index 84410ed..e651287 100644
--- a/WatchFace.Parser/Reader.cs
+++ b/WatchFace.Parser/Reader.cs
@@ -1,8 +1,8 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Drawing;
using System.IO;
using NLog;
-using System.Drawing;
+using Resources;
using WatchFace.Parser.Models;
namespace WatchFace.Parser
@@ -18,8 +18,8 @@ namespace WatchFace.Parser
_fileStream = streamReader;
}
- public List Resources { get; private set; }
- public List Images { get; private set; }
+ public List Parameters { get; private set; }
+ public Bitmap[] Images { get; private set; }
public void Read()
{
@@ -38,51 +38,36 @@ namespace WatchFace.Parser
Logger.Trace("Reading parameters descriptor...");
var mainParam = Parameter.ReadFrom(parametersStream);
Logger.Trace("Parameters descriptor was read:");
- var coordinatesTableSize = mainParam.Children[0].Value;
- var imagesTableLength = mainParam.Children[1].Value;
- Logger.Trace($"CoordinatesTableSize: {coordinatesTableSize}, ImagesTableLength: {imagesTableLength}");
+ var parametrsTableLength = mainParam.Children[0].Value;
+ var imagesCount = mainParam.Children[1].Value;
+ Logger.Trace($"ParametrsTableLength: {parametrsTableLength}, ImagesCount: {imagesCount}");
- Logger.Trace("Reading face parameters...");
- var parameters = Parameter.ReadList(parametersStream);
- Logger.Trace("Watch face parameters were read:");
+ Logger.Trace("Reading parameters locations...");
+ var parametersLocations = Parameter.ReadList(parametersStream);
+ Logger.Trace("Watch face parameters locations were read:");
- ParseResources(coordinatesTableSize, parameters);
- ParseImages(imagesTableLength);
+ Parameters = ReadParameters(parametrsTableLength, parametersLocations);
+ Images = new ResourcesReader(_fileStream).Read((uint) imagesCount);
}
- private void ParseResources(long coordinatesTableSize, IReadOnlyCollection parameters)
+ private List ReadParameters(long coordinatesTableSize,
+ IReadOnlyCollection parametersDescriptors)
{
- var coordsStream = StreamBlock(_fileStream, (int) coordinatesTableSize);
+ var parametersStream = StreamBlock(_fileStream, (int) coordinatesTableSize);
- Resources = new List(parameters.Count);
- foreach (var parameter in parameters)
+ var result = new List(parametersDescriptors.Count);
+ foreach (var prameterDescriptor in parametersDescriptors)
{
- Logger.Trace("Reading descriptor for parameter {0}", parameter.Id);
- var descriptorOffset = parameter.Children[0].Value;
- var descriptorLength = parameter.Children[1].Value;
+ var descriptorOffset = prameterDescriptor.Children[0].Value;
+ var descriptorLength = prameterDescriptor.Children[1].Value;
+ Logger.Trace("Reading descriptor for parameter {0}", prameterDescriptor.Id);
Logger.Trace("Descriptor offset: {0}, Descriptor length: {1}", descriptorOffset, descriptorLength);
- coordsStream.Seek(descriptorOffset, SeekOrigin.Begin);
- var descriptorStream = StreamBlock(coordsStream, (int) descriptorLength);
- Logger.Trace("Parsing descriptor for parameter {0}...", parameter.Id);
- Resources.Add(new Parameter(parameter.Id, Parameter.ReadList(descriptorStream)));
- }
- }
-
- private void ParseImages(long imagesTableLength)
- {
- var imagesOffsets = new byte[imagesTableLength * 4];
- _fileStream.Read(imagesOffsets, 0, imagesOffsets.Length);
-
- var imagesOffset = _fileStream.Position;
-
- Images = new List((int) imagesTableLength);
- for (var i = 0; i < (int) imagesTableLength; i++)
- {
- var imageOffset = BitConverter.ToUInt32(imagesOffsets, i * 4) + imagesOffset;
- _fileStream.Seek(imageOffset, SeekOrigin.Begin);
- var image = new ImageReader(_fileStream).Read();
- Images.Add(image);
+ parametersStream.Seek(descriptorOffset, SeekOrigin.Begin);
+ var descriptorStream = StreamBlock(parametersStream, (int) descriptorLength);
+ Logger.Trace("Parsing descriptor for parameter {0}...", prameterDescriptor.Id);
+ result.Add(new Parameter(prameterDescriptor.Id, Parameter.ReadList(descriptorStream)));
}
+ return result;
}
private static Stream StreamBlock(Stream stream, int size)
diff --git a/WatchFace.Parser/Utils/ParametersConverter.cs b/WatchFace.Parser/Utils/ParametersConverter.cs
index 9e74a84..b0ab9ac 100644
--- a/WatchFace.Parser/Utils/ParametersConverter.cs
+++ b/WatchFace.Parser/Utils/ParametersConverter.cs
@@ -31,26 +31,31 @@ namespace WatchFace.Parser.Utils
return result;
}
- public static T Parse(List descriptor, string path = "") where T : new()
+ public static T Parse(List descriptor, string path = "", int traceOffset = 0) where T : new()
{
var properties = SortedPropertiesDictionary();
-
var result = new T();
- Logger.Trace("Reading {0} {1}", typeof(T).Name, path);
+ var currentType = typeof(T);
+
+ if (!string.IsNullOrEmpty(path))
+ Logger.Trace("{0} '{1}'", path, currentType.Name);
foreach (var parameter in descriptor)
{
- var currentPath = string.Concat(path, '.', parameter.Id.ToString());
- var propertyInfo = properties[parameter.Id];
- if (propertyInfo == null)
- throw new InvalidParameterException(parameter, path);
+ var currentPath = string.IsNullOrEmpty(path)
+ ? parameter.Id.ToString()
+ : string.Concat(path, '.', parameter.Id.ToString());
+ if (!properties.ContainsKey(parameter.Id))
+ throw new ArgumentException($"Parameter {parameter.Id} isn't supported for {currentType.Name}");
+ var propertyInfo = properties[parameter.Id];
var propertyType = propertyInfo.PropertyType;
if (propertyType == typeof(long))
{
+ Logger.Trace("{0} '{1}': {2}", currentPath, propertyInfo.Name, parameter.Value);
dynamic propertyValue = propertyInfo.GetValue(result);
if (propertyValue != 0)
- throw new DuplicateParameterException(parameter, path);
+ throw new ArgumentException($"Parameter {parameter.Id} is already set for {currentType.Name}");
propertyInfo.SetValue(result, parameter.Value);
}
@@ -68,7 +73,8 @@ namespace WatchFace.Parser.Utils
var method = typeof(ParametersConverter).GetMethod(nameof(Parse));
var itemType = propertyType.GetGenericArguments()[0];
var generic = method.MakeGenericMethod(itemType);
- dynamic parsedValue = generic.Invoke(null, new dynamic[] {parameter.Children, currentPath});
+ dynamic parsedValue = generic.Invoke(null,
+ new dynamic[] {parameter.Children, currentPath, traceOffset + 1});
propertyValue.Add(parsedValue);
}
catch (TargetInvocationException e)
@@ -80,13 +86,14 @@ namespace WatchFace.Parser.Utils
{
dynamic propertyValue = propertyInfo.GetValue(result);
if (propertyValue != null)
- throw new DuplicateParameterException(parameter, path);
+ throw new ArgumentException($"Parameter {parameter.Id} is already set for {currentType.Name}");
try
{
var method = typeof(ParametersConverter).GetMethod(nameof(Parse));
var generic = method.MakeGenericMethod(propertyType);
- dynamic parsedValue = generic.Invoke(null, new dynamic[] {parameter.Children, currentPath});
+ dynamic parsedValue = generic.Invoke(null,
+ new dynamic[] {parameter.Children, currentPath, traceOffset + 1});
propertyInfo.SetValue(result, parsedValue);
}
catch (TargetInvocationException e)
diff --git a/WatchFace.Parser/WatchFace.Parser.csproj b/WatchFace.Parser/WatchFace.Parser.csproj
index 7a12800..85072f8 100644
--- a/WatchFace.Parser/WatchFace.Parser.csproj
+++ b/WatchFace.Parser/WatchFace.Parser.csproj
@@ -61,7 +61,7 @@
-
+
@@ -76,16 +76,12 @@
-
-
-
-
@@ -95,5 +91,11 @@
+
+
+ {edd55d5d-9e80-451b-ac8a-0746ba6dc6e9}
+ Resources
+
+
\ No newline at end of file
diff --git a/WatchFace.Parser/WatchFace.cs b/WatchFace.Parser/WatchFace.cs
index 5c413de..ef7dd94 100644
--- a/WatchFace.Parser/WatchFace.cs
+++ b/WatchFace.Parser/WatchFace.cs
@@ -21,7 +21,7 @@ namespace WatchFace.Parser
public Weather Weather { get; set; }
[RawParameter(Id = 7)]
- public Scales Scales { get; set; }
+ public StepsProgress StepsProgress { get; set; }
[RawParameter(Id = 8)]
public Status Status { get; set; }
diff --git a/WatchFace/Program.cs b/WatchFace/Program.cs
index 595c5b7..cca9173 100644
--- a/WatchFace/Program.cs
+++ b/WatchFace/Program.cs
@@ -1,12 +1,15 @@
using System;
+using System.Collections.Generic;
+using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using Newtonsoft.Json;
using NLog;
using NLog.Config;
using NLog.Targets;
-using WatchFace.Parser.Utils;
+using Resources;
using WatchFace.Parser;
+using WatchFace.Parser.Utils;
namespace WatchFace
{
@@ -21,21 +24,47 @@ namespace WatchFace
if (args.Length == 0 || args[0] == null)
{
Console.WriteLine("{0} unpacks Amazfit Bip downloadable watch faces.", AppName);
- Console.WriteLine("Usage: {0}.exe watchface.bin", AppName);
+ Console.WriteLine("Usage: {0}.exe wf.bin [wf2.bin] ...", AppName);
return;
}
- var inputFileName = args[0];
- if (!File.Exists(inputFileName))
+ if (args.Length > 0)
+ Console.WriteLine("Multiple files unpacking.");
+
+ foreach (var inputFileName in args)
{
- Console.WriteLine("File '{0}' doesn't exists.", inputFileName);
- return;
- }
+ if (!File.Exists(inputFileName))
+ {
+ Console.WriteLine("File '{0}' doesn't exists.", inputFileName);
+ continue;
+ }
- if (Path.GetExtension(inputFileName) == ".json")
- PackWatchFace(inputFileName);
- else
- UnpackWatchFace(inputFileName);
+ Console.WriteLine("Processing file '{0}'", inputFileName);
+ var inputFileExtension = Path.GetExtension(inputFileName);
+ try
+ {
+ switch (inputFileExtension)
+ {
+ case ".bin":
+ UnpackWatchFace(inputFileName);
+ break;
+ case ".json":
+ PackWatchFace(inputFileName);
+ break;
+ case ".res":
+ UnpackResources(inputFileName);
+ break;
+ default:
+ Console.WriteLine("The app doesn't support files with extension {0}.", inputFileExtension);
+ Console.WriteLine("Only 'bin', 'res' and 'json' files are supported at this time.");
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Fatal(e);
+ }
+ }
}
private static void PackWatchFace(string inputFileName)
@@ -59,10 +88,25 @@ namespace WatchFace
if (watchFace == null) return;
Logger.Debug("Exporting resources to '{0}'", outputDirectory);
- ExportImages(reader, outputDirectory);
+ new ResourcesExtractor(reader.Images).Extract(outputDirectory);
ExportConfig(watchFace, Path.Combine(outputDirectory, $"{baseName}.json"));
}
+ private static void UnpackResources(string inputFileName)
+ {
+ var outputDirectory = CreateOutputDirectory(inputFileName);
+ var baseName = Path.GetFileNameWithoutExtension(inputFileName);
+ SetupLogger(Path.Combine(outputDirectory, $"{baseName}.log"));
+
+ Bitmap[] images;
+ using (var stream = File.OpenRead(inputFileName))
+ {
+ images = new ResourcesFileReader(stream).Read();
+ }
+
+ new ResourcesExtractor(images).Extract(outputDirectory);
+ }
+
private static void WriteWatchFace(string outputFileName, Parser.WatchFace watchFace)
{
Logger.Debug("Writing watch face to '{0}'", outputFileName);
@@ -106,7 +150,7 @@ namespace WatchFace
Logger.Debug("Parsing parameters...");
try
{
- return ParametersConverter.Parse(reader.Resources);
+ return ParametersConverter.Parse(reader.Parameters);
}
catch (Exception e)
{
@@ -124,24 +168,6 @@ namespace WatchFace
return unpackedPath;
}
- private static void ExportImages(Reader reader, string outputDirectory)
- {
- Logger.Debug("Exporting images...");
- try
- {
- var index = 0;
- foreach (var image in reader.Images)
- {
- image.Save(Path.Combine(outputDirectory, $"{index}.bmp"), ImageFormat.Bmp);
- index++;
- }
- }
- catch (Exception e)
- {
- Logger.Fatal(e);
- }
- }
-
private static Parser.WatchFace ReadConfig(string jsonFileName)
{
Logger.Debug("Reading config...");
diff --git a/WatchFace/WatchFace.csproj b/WatchFace/WatchFace.csproj
index d2d099b..798382d 100644
--- a/WatchFace/WatchFace.csproj
+++ b/WatchFace/WatchFace.csproj
@@ -57,6 +57,10 @@
+
+ {edd55d5d-9e80-451b-ac8a-0746ba6dc6e9}
+ Resources
+
{77d5f357-a1f3-4823-a328-b78b49ed870a}
WatchFace.Parser