├── .gitignore
├── Hex2Bin.csproj
├── Hex2Bin.sln
├── Program.cs
├── Properties
└── AssemblyInfo.cs
├── README.md
└── bin
└── Debug
└── Hex2Bin.exe
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Oo]bj/
3 |
4 | # mstest test results
5 | TestResults
6 |
7 | ## Ignore Visual Studio temporary files, build results, and
8 | ## files generated by popular Visual Studio add-ons.
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.sln.docstates
14 |
15 | # Build results
16 | [Rr]elease/
17 | x64/
18 | *_i.c
19 | *_p.c
20 | *.ilk
21 | *.meta
22 | *.obj
23 | *.pch
24 | *.pdb
25 | *.pgc
26 | *.pgd
27 | *.rsp
28 | *.sbr
29 | *.tlb
30 | *.tli
31 | *.tlh
32 | *.tmp
33 | *.log
34 | *.vspscc
35 | *.vssscc
36 | .builds
37 |
38 | # Visual C++ cache files
39 | ipch/
40 | *.aps
41 | *.ncb
42 | *.opensdf
43 | *.sdf
44 |
45 | # Visual Studio profiler
46 | *.psess
47 | *.vsp
48 | *.vspx
49 |
50 | # Guidance Automation Toolkit
51 | *.gpState
52 |
53 | # ReSharper is a .NET coding add-in
54 | _ReSharper*
55 |
56 | # NCrunch
57 | *.ncrunch*
58 | .*crunch*.local.xml
59 |
60 | # Installshield output folder
61 | [Ee]xpress
62 |
63 | # DocProject is a documentation generator add-in
64 | DocProject/buildhelp/
65 | DocProject/Help/*.HxT
66 | DocProject/Help/*.HxC
67 | DocProject/Help/*.hhc
68 | DocProject/Help/*.hhk
69 | DocProject/Help/*.hhp
70 | DocProject/Help/Html2
71 | DocProject/Help/html
72 |
73 | # Click-Once directory
74 | publish
75 |
76 | # Publish Web Output
77 | *.Publish.xml
78 |
79 | # NuGet Packages Directory
80 | packages
81 |
82 | # Windows Azure Build Output
83 | csx
84 | *.build.csdef
85 |
86 | # Windows Store app package directory
87 | AppPackages/
88 |
89 | # Others
90 | [Oo]bj
91 | sql
92 | TestResults
93 | [Tt]est[Rr]esult*
94 | *.Cache
95 | ClientBin
96 | [Ss]tyle[Cc]op.*
97 | ~$*
98 | *.dbmdl
99 | Generated_Code #added for RIA/Silverlight projects
100 |
101 | # Backup & report files from converting an old project file to a newer
102 | # Visual Studio version. Backup files are not needed, because we have git ;-)
103 | _UpgradeReport_Files/
104 | Backup*/
105 | UpgradeLog*.XML
106 |
--------------------------------------------------------------------------------
/Hex2Bin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 9.0.30729
7 | 2.0
8 | {F2742C17-3333-4DD3-9DD7-0EE274B03728}
9 | Exe
10 | Properties
11 | Hex2Bin
12 | hex2bin
13 | v2.0
14 | 512
15 |
16 |
17 | 3.5
18 |
19 | publish\
20 | true
21 | Disk
22 | false
23 | Foreground
24 | 7
25 | Days
26 | false
27 | false
28 | true
29 | 0
30 | 1.0.0.%2a
31 | false
32 | false
33 | true
34 |
35 |
36 | true
37 | full
38 | false
39 | bin\Debug\
40 | DEBUG;TRACE
41 | prompt
42 | 4
43 | AllRules.ruleset
44 | false
45 | x86
46 |
47 |
48 | pdbonly
49 | true
50 | bin\Release\
51 | TRACE
52 | prompt
53 | 4
54 | AllRules.ruleset
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | False
66 | .NET Framework 3.5 SP1 Client Profile
67 | false
68 |
69 |
70 | False
71 | .NET Framework 3.5 SP1
72 | true
73 |
74 |
75 | False
76 | Windows Installer 3.1
77 | true
78 |
79 |
80 |
81 |
88 |
--------------------------------------------------------------------------------
/Hex2Bin.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hex2Bin", "Hex2Bin.csproj", "{F2742C17-3333-4DD3-9DD7-0EE274B03728}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Release|Any CPU = Release|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {F2742C17-3333-4DD3-9DD7-0EE274B03728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {F2742C17-3333-4DD3-9DD7-0EE274B03728}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {F2742C17-3333-4DD3-9DD7-0EE274B03728}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {F2742C17-3333-4DD3-9DD7-0EE274B03728}.Release|Any CPU.Build.0 = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using System.IO;
5 | using System.Globalization;
6 |
7 | namespace Hex2Bin
8 | {
9 | enum FileFormat
10 | {
11 | Auto,
12 | Bin,
13 | Hex,
14 | Jam
15 | }
16 |
17 | class Program
18 | {
19 | static byte[] Memory = null;
20 |
21 | static uint MemoryLow = uint.MaxValue;
22 | static uint MemoryHigh = uint.MinValue;
23 |
24 | static uint AddressMax = 0;
25 | static uint AddressMin = uint.MaxValue;
26 |
27 | static uint BaseAddress = 0;
28 | static bool BaseAddressDefine = false;
29 |
30 | static uint MemoryStart = 0;
31 | static bool IsMemoryStart = false;
32 |
33 | static uint MemoryEnd = 0;
34 | static bool IsMemoryEnd = false;
35 |
36 | static uint MemoryLength = 0;
37 | static bool IsMemoryLength = false;
38 |
39 | static bool ScanOnly = false;
40 | static bool MakeCode = false;
41 | static bool ExtractCode = false;
42 | static byte EmptyValue = 0xFF;
43 |
44 | const uint BLOCK_SIZE = 1024;
45 |
46 | static void usageHelp()
47 | {
48 | Console.Write(@"
49 | Hex2Bin [options] in-file.hex|bin|s|jam [out-file]
50 | -h[elp] display this text
51 | -b[ase]=address set base address (0x... for hex)
52 | -ml=length set memory length (0x... for hex)
53 | -ms=address set memory start address (0x... for hex)
54 | -me=address set memory end address (0x... for hex)
55 | -s[can] scan file for min/max addresses
56 | -c[ode] convert to C text
57 | -f[ill]=value fill value for empty memory
58 | -ex[tract] extract from base (-b) to end (-e) or length (-l)
59 | -mcu=PIC24FJ256 allocate memory ones (256K)
60 | -mcu=PIC24FJ128 allocate memory ones (128K)
61 | -bin force input format to BINARY format
62 | -hex force input format to HEX format
63 | -jam force input format to JAM format
64 | Process .jam (Microchip format) file and make one image file
65 | .hex Intel hex format file
66 | .s Motorola format file
67 | .bin binary file
68 | "
69 | );
70 | }
71 |
72 | static void Main(string[] args)
73 | {
74 | string fileIn = null;
75 | string fileOut = null;
76 | int exitCode = 0;
77 | FileFormat input_type = FileFormat.Auto;
78 | if (args.Length == 0)
79 | {
80 | usageHelp();
81 | Environment.Exit(1);
82 | }
83 |
84 | #region Options
85 | foreach (string arg in args)
86 | {
87 | if (arg.StartsWith("-", StringComparison.InvariantCulture) ||
88 | arg.StartsWith("/", StringComparison.InvariantCulture)
89 | )
90 | {
91 | #region Process options
92 |
93 | string[] option = arg.Substring(1).Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
94 | string value = string.Empty;
95 | if (option.Length == 2)
96 | value = option[1].Trim();
97 |
98 | switch (option[0].ToLowerInvariant())
99 | {
100 | case "hex":
101 | input_type = FileFormat.Hex;
102 | break;
103 | case "bin":
104 | input_type = FileFormat.Bin;
105 | break;
106 | case "jam":
107 | input_type = FileFormat.Jam;
108 | break;
109 | case "mcu":
110 | #region Set PIC type
111 | switch (value.ToUpperInvariant())
112 | {
113 | case "PIC24FJ256":
114 | Memory = new byte[256 * 1024];
115 | break;
116 | case "PIC24FJ128":
117 | Memory = new byte[128 * 1024];
118 | break;
119 | default:
120 | Console.WriteLine(string.Format("Unknown -mcu {0}", value));
121 | exitCode = 1;
122 | break;
123 | }
124 | break;
125 | #endregion
126 | case "b":
127 | case "base":
128 | #region Set base address
129 | if (!string.IsNullOrEmpty(value))
130 | {
131 | if (IsMemoryEnd)
132 | {
133 | Console.WriteLine("Can set Base Address only ones.");
134 | }
135 | else if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
136 | { // Hex format 0x....
137 | if ((BaseAddressDefine = uint.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out BaseAddress)))
138 | break;
139 | }
140 | else
141 | {
142 | if ((BaseAddressDefine = uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out BaseAddress)))
143 | break;
144 | }
145 | }
146 | exitCode = 1;
147 | break;
148 | #endregion
149 | case "ms":
150 | #region Set start address
151 | if (!string.IsNullOrEmpty(value))
152 | {
153 | if (IsMemoryStart)
154 | {
155 | Console.WriteLine("Can set Start Address only ones.");
156 | }
157 | else if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
158 | { // Hex format 0x....
159 | if ((IsMemoryStart = uint.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out MemoryStart)))
160 | break;
161 | }
162 | else
163 | {
164 | if ((IsMemoryStart = uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out MemoryStart)))
165 | break;
166 | }
167 | }
168 | exitCode = 1;
169 | break;
170 | #endregion
171 | case "me":
172 | #region Set end address
173 | if (!string.IsNullOrEmpty(value))
174 | {
175 | if (IsMemoryLength)
176 | {
177 | Console.WriteLine("Can't set both End Address and Length");
178 | }
179 | else if (IsMemoryEnd)
180 | {
181 | Console.WriteLine("Can set End Address only ones.");
182 | }
183 | else if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
184 | { // Hex format 0x....
185 | if ((IsMemoryEnd = uint.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out MemoryEnd)))
186 | break;
187 | }
188 | else
189 | {
190 | if ((IsMemoryEnd = uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out MemoryEnd)))
191 | break;
192 | }
193 | }
194 | exitCode = 1;
195 | break;
196 | #endregion
197 | case "ml":
198 | #region Set length
199 | if (!string.IsNullOrEmpty(value))
200 | {
201 | if (IsMemoryEnd)
202 | {
203 | Console.WriteLine("Can't set both End Address and Length");
204 | }
205 | else if (IsMemoryLength)
206 | {
207 | Console.WriteLine("Can set Length only ones.");
208 | }
209 | else if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
210 | { // Hex format 0x....
211 | if ((IsMemoryLength = uint.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out MemoryLength)))
212 | break;
213 | }
214 | else
215 | {
216 | if ((IsMemoryLength = uint.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out MemoryLength)))
217 | break;
218 | }
219 | }
220 | exitCode = 1;
221 | break;
222 | #endregion
223 | case "f":
224 | case "fill":
225 | #region Set empty memory value
226 | if (!string.IsNullOrEmpty(value))
227 | {
228 | if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
229 | { // Hex format 0x
230 | if (byte.TryParse(value.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out EmptyValue))
231 | break;
232 | }
233 | else
234 | { // Decimal format
235 | if (byte.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out EmptyValue))
236 | break;
237 | }
238 | }
239 | exitCode = 1;
240 | break;
241 | #endregion
242 | case "s":
243 | case "scan":
244 | ScanOnly = true;
245 | break;
246 | case "c":
247 | case "code":
248 | MakeCode = true;
249 | break;
250 | case "ex":
251 | case "extract":
252 | ExtractCode = true;
253 | break;
254 | default:
255 | #region Unknown option
256 | Console.WriteLine(string.Format("Unknown option {0}", arg));
257 | exitCode = 1;
258 | break;
259 | #endregion
260 | }
261 | #endregion
262 | }
263 | else if (fileIn == null)
264 | fileIn = arg; // First paramter as input file
265 | else if (fileOut == null)
266 | fileOut = arg; // Second paramter as output file
267 | else
268 | {
269 | Console.WriteLine("Too many files define.");
270 | exitCode = 1;
271 | }
272 | if (exitCode != 0)
273 | Environment.Exit(exitCode);
274 | }
275 | #endregion
276 |
277 | if (string.IsNullOrEmpty(fileIn))
278 | {
279 | Console.WriteLine("No input file.");
280 | Environment.Exit(1);
281 | }
282 |
283 | if (!File.Exists(fileIn))
284 | {
285 | Console.WriteLine(string.Format("Input file {0} not found.", fileIn));
286 | Environment.Exit(1);
287 | }
288 |
289 | #region Load file
290 | string ext = Path.GetExtension(fileIn).ToLowerInvariant();
291 | if (input_type == FileFormat.Auto)
292 | {
293 | switch (ext)
294 | {
295 | case ".bin":
296 | input_type = FileFormat.Bin;
297 | break;
298 | case ".hex":
299 | input_type = FileFormat.Hex;
300 | break;
301 | case ".jam":
302 | input_type = FileFormat.Jam;
303 | break;
304 | default:
305 | Console.WriteLine("Unknown extension {0}", ext);
306 | Environment.Exit(1);
307 | break;
308 | }
309 | }
310 |
311 | switch (input_type)
312 | {
313 | case FileFormat.Jam:
314 | input_type = FileFormat.Hex;
315 | #region Process Microchip JAM file
316 | // Each line is HEX file name
317 | using (TextReader s = new StreamReader(fileIn))
318 | {
319 | string filename;
320 | while ((filename = s.ReadLine()) != null)
321 | {
322 | filename = filename.Trim();
323 | if (filename.Length == 0)
324 | continue;
325 | Console.WriteLine(string.Format("Process file:{0}", filename));
326 | exitCode = loadHex(filename);
327 | if (exitCode != 0)
328 | break;
329 | }
330 | }
331 | break;
332 | #endregion
333 | case FileFormat.Hex:
334 | exitCode = loadHex(fileIn);
335 | break;
336 | case FileFormat.Bin:
337 | exitCode = loadBin(fileIn);
338 | break;
339 | }
340 |
341 | if ((exitCode == 0) && (Memory == null || Memory.Length == 0))
342 | {
343 | Console.WriteLine("Empty input data.");
344 | exitCode = 1;
345 | }
346 |
347 | if (exitCode != 0)
348 | Environment.Exit(exitCode);
349 | #endregion
350 |
351 | Console.WriteLine("Memory Address range: 0x{0:X}-0x{1:X}", AddressMin, AddressMax);
352 |
353 | #region Check Addresses
354 | if (!IsMemoryStart)
355 | MemoryStart = AddressMin;
356 | if (IsMemoryLength)
357 | MemoryEnd = MemoryStart + MemoryLength - 1;
358 | else if (!IsMemoryEnd)
359 | MemoryEnd = AddressMax;
360 |
361 | if (AddressMin != 0 && MemoryStart < AddressMin)
362 | {
363 | Console.WriteLine("Start Address must be great or equal Memory Min. Address");
364 | Environment.Exit(1);
365 | }
366 | if (MemoryEnd < MemoryStart)
367 | {
368 | Console.WriteLine("End Address must be great or equal Start Address");
369 | Environment.Exit(1);
370 | }
371 | else if (MemoryEnd > AddressMax)
372 | {
373 | Console.WriteLine("End Address must be less than Memory Max. Address");
374 | Environment.Exit(1);
375 | }
376 | #endregion
377 |
378 | #region Save internal memory to binary file
379 |
380 | if (MakeCode)
381 | {
382 | #region MakeCode
383 |
384 | if (fileOut == null)
385 | fileOut = string.Concat(Path.GetFileNameWithoutExtension(fileIn), ".c");
386 |
387 | using (FileStream fs = new FileStream(fileOut, File.Exists(fileOut) ? FileMode.Truncate : FileMode.Create, FileAccess.Write))
388 | {
389 | using (StreamWriter sw = new StreamWriter(fs, Encoding.Default))
390 | {
391 | int row_count = 0;
392 | int length = (int)(MemoryEnd - MemoryStart + 1);
393 | sw.Write(string.Format(@"
394 | #include
395 |
396 | /*
397 | * File: {0}
398 | * Address range: 0x{1:X}-0x{2:X}
399 | */
400 | const PROGMEM uint8_t {3}[{4}]
401 | // __attribute__((used))
402 | // __attribute__((section("".flash_0x{1:X}"")))
403 | = {{",
404 | fileIn,
405 | BaseAddress, MemoryEnd,
406 | Path.GetFileNameWithoutExtension(fileIn).Replace("-", "_"),
407 | length
408 | )
409 | );
410 |
411 | int address = (int)(MemoryStart - AddressMin);
412 | while (length != 0)
413 | {
414 | length--;
415 | if (row_count == 0)
416 | {
417 | if (length != 0)
418 | sw.Write(",");
419 | sw.Write("\r\n\t");
420 | row_count = 16;
421 | }
422 | else
423 | {
424 | sw.Write(", ");
425 | }
426 | --row_count;
427 |
428 | sw.Write(string.Format("0x{0:X2}", Memory[address++]));
429 | }
430 | sw.Write(@"
431 | };
432 | ");
433 | sw.Close();
434 | }
435 | }
436 | #endregion
437 | }
438 | else if (ExtractCode)
439 | {
440 | #region Extract
441 | if (fileOut == null)
442 | {
443 | Console.WriteLine("Must define output file name");
444 | Environment.Exit(1);
445 | }
446 | exitCode = writeToBin(fileOut);
447 | #endregion
448 | }
449 | else if (!ScanOnly)
450 | {
451 | switch (input_type)
452 | {
453 | case FileFormat.Bin:
454 | if (fileOut == null)
455 | fileOut = string.Concat(Path.GetFileNameWithoutExtension(fileIn), ".hex");
456 | exitCode = writeToHex(fileOut);
457 | break;
458 | case FileFormat.Hex:
459 | if (fileOut == null)
460 | fileOut = string.Concat(Path.GetFileNameWithoutExtension(fileIn), ".bin");
461 | exitCode = writeToBin(fileOut);
462 | break;
463 | default:
464 | break;
465 | }
466 | }
467 | #endregion
468 | Environment.Exit(exitCode);
469 | }
470 |
471 | private static int writeToBin(string fileOut)
472 | {
473 | int exitcode = 0;
474 | try
475 | {
476 | using (Stream s = File.Open(fileOut, File.Exists(fileOut) ? FileMode.Truncate : FileMode.Create, FileAccess.Write))
477 | {
478 | s.Write(Memory, (int)(MemoryStart - AddressMin), (int)(MemoryEnd - MemoryStart + 1));
479 | s.Close();
480 | }
481 | }
482 | catch(Exception ex)
483 | {
484 | Console.WriteLine(ex.Message);
485 | exitcode = -1;
486 | }
487 | return exitcode;
488 | }
489 |
490 | #region loadBin(string fileIn)
491 | ///
492 | /// Convert binary file to hex format
493 | ///
494 | ///
495 | ///
496 | private static int loadBin(string fileIn)
497 | {
498 | int exitCode = 0;
499 |
500 | try
501 | {
502 | using (FileStream fs = new FileStream(fileIn, FileMode.Open))
503 | {
504 | using (BinaryReader b = new BinaryReader(fs))
505 | {
506 | Memory = new byte[fs.Length];
507 | b.Read(Memory, 0, (int)fs.Length);
508 | b.Close();
509 | }
510 | fs.Close();
511 | }
512 | if (Memory != null && Memory.Length > 0)
513 | {
514 | AddressMin = 0;
515 | AddressMax = (uint)Memory.Length - 1;
516 | }
517 | }
518 | catch (Exception ex)
519 | {
520 | Console.WriteLine(ex.Message);
521 | exitCode = 1;
522 | }
523 | return exitCode;
524 | }
525 | #endregion
526 |
527 | #region writeToHex(string fileOut)
528 | private static int writeToHex(string fileOut)
529 | {
530 | uint out_address = BaseAddress;
531 | uint hex_address = 0;
532 | int exitCode = 0;
533 |
534 | try
535 | {
536 | // Convert to HEX file
537 | uint byte_index = MemoryStart;
538 | StringBuilder sb = new StringBuilder(50);
539 | uint cs;
540 |
541 | using (FileStream fs = new FileStream(fileOut, FileMode.Create, FileAccess.Write))
542 | {
543 | using (TextWriter w = new StreamWriter(fs))
544 | {
545 | while (byte_index <= MemoryEnd)
546 | {
547 | sb.Remove(0, sb.Length);
548 | if (hex_address != (out_address & 0xFFFF0000))
549 | {
550 | cs = 2 + (uint)INTEL_COMMAND.EXTEND_ADDR + ((out_address >> 16) & 0xFF) + ((out_address >> 24) & 0xFF);
551 | sb.AppendFormat(":020000{0:X2}{1:X4}{2:X2}", (uint)INTEL_COMMAND.EXTEND_ADDR, (out_address >> 16) & 0xFFFF, ((cs ^ 0xFF) + 1) & 0xFF);
552 | w.WriteLine(sb.ToString());
553 | hex_address = (out_address & 0xFFFF0000);
554 | sb.Remove(0, sb.Length);
555 | }
556 |
557 | uint byte_count = Math.Min((uint)16, (uint)(MemoryEnd - byte_index + 1));
558 | sb.AppendFormat(":{0:X2}{1:X4}{2:X2}", byte_count, out_address & 0xFFFF, (uint)INTEL_COMMAND.DATA);
559 | cs = byte_count + (out_address & 0xFF) + (out_address >> 8 & 0xFF) + (uint)INTEL_COMMAND.DATA;
560 | while (byte_count > 0)
561 | {
562 | byte data = Memory[byte_index++];
563 | cs += data;
564 | sb.AppendFormat("{0:X2}", data);
565 | out_address++;
566 | --byte_count;
567 | }
568 | sb.AppendFormat("{0:X2}", ((cs ^ 0xFF) + 1) & 0xFF);
569 | w.WriteLine(sb.ToString());
570 | }
571 | w.WriteLine(":00000001FF");
572 | w.Close();
573 | }
574 | fs.Close();
575 | }
576 | }
577 | catch (Exception ex)
578 | {
579 | Console.WriteLine(ex.Message);
580 | exitCode = 1;
581 | }
582 | return exitCode;
583 | }
584 | #endregion
585 |
586 | #region loadHex(string fileIn)
587 | enum MOTOROLA_COMMAND : byte
588 | {
589 | CMD_00 = 0x00,
590 | CMD_01 = 0x01,
591 | CMD_02 = 0x02,
592 | CMD_03 = 0x03,
593 | CMD_04 = 0x04,
594 | CMD_05 = 0x05,
595 | CMD_06 = 0x06,
596 | CMD_07 = 0x07,
597 | CMD_08 = 0x08,
598 | CMD_09 = 0x09
599 | }
600 | enum INTEL_COMMAND : byte
601 | {
602 | UNKNOWN = 0xFF,
603 | DATA = 0x00,
604 | EOF = 0x01,
605 | EXT_SEGMENT_ADDR = 0x02,
606 | SEGMENT_ADDR = 0x03,
607 | EXTEND_ADDR = 0x04,
608 | LINEAR_ADDR = 0x05,
609 | DATA_LOOP = 0x10
610 | }
611 |
612 | ///
613 | /// Convert HEX|S file to internal byte array
614 | ///
615 | ///
616 | /// error code (0=none)
617 | private static int loadHex(string fileIn)
618 | {
619 | uint extend_address = 0, start_address = 0, segment_address = 0, linear_address = 0;
620 | string line;
621 | int lineNumber = 0;
622 | bool fail = false;
623 | uint count = 0, address = 0;
624 | byte data = 0, checksum;
625 | int idx = 0;
626 | INTEL_COMMAND command = INTEL_COMMAND.UNKNOWN;
627 |
628 | using (TextReader s = new StreamReader(fileIn))
629 | {
630 | while ((line = s.ReadLine()) != null)
631 | {
632 | ++lineNumber;
633 | line = line.Trim();
634 | if (line.Length == 0)
635 | continue;
636 |
637 | if (line.StartsWith("S"))
638 | {
639 | #region Motorola format
640 | // Stccaaaaaaadd...ddss
641 | if (line.Length < 9)
642 | {
643 | fail = true;
644 | }
645 | else
646 | {
647 | fail |= !byte.TryParse(line.Substring(1, 1), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data);
648 | MOTOROLA_COMMAND m_command = (MOTOROLA_COMMAND)data;
649 | switch (m_command)
650 | {
651 | case MOTOROLA_COMMAND.CMD_01:
652 | fail |= !uint.TryParse(line.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count);
653 | fail |= !uint.TryParse(line.Substring(4, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address);
654 | command = INTEL_COMMAND.DATA_LOOP;
655 | idx = 8;
656 | count -= 3;
657 | break;
658 | case MOTOROLA_COMMAND.CMD_02:
659 | if (line.Length < 11)
660 | {
661 | fail = true;
662 | }
663 | else
664 | {
665 | fail |= !uint.TryParse(line.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count);
666 | fail |= !uint.TryParse(line.Substring(4, 6), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address);
667 | }
668 | command = INTEL_COMMAND.DATA_LOOP;
669 | idx = 10;
670 | count -= 4;
671 | break;
672 | case MOTOROLA_COMMAND.CMD_03:
673 | if (line.Length < 13)
674 | {
675 | fail = true;
676 | }
677 | else
678 | {
679 | fail |= !uint.TryParse(line.Substring(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count);
680 | fail |= !uint.TryParse(line.Substring(4, 8), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address);
681 | }
682 | command = INTEL_COMMAND.DATA_LOOP;
683 | idx = 12;
684 | count -= 5;
685 | break;
686 | case MOTOROLA_COMMAND.CMD_00:
687 | case MOTOROLA_COMMAND.CMD_04:
688 | case MOTOROLA_COMMAND.CMD_05:
689 | case MOTOROLA_COMMAND.CMD_06:
690 | fail = true;
691 | break;
692 | case MOTOROLA_COMMAND.CMD_07:
693 | case MOTOROLA_COMMAND.CMD_08:
694 | case MOTOROLA_COMMAND.CMD_09:
695 | continue;
696 | }
697 | }
698 | #endregion
699 | }
700 | else if (line.StartsWith(":"))
701 | {
702 | #region Intel format
703 | if (line.Length < 11)
704 | {
705 | fail = true;
706 | }
707 | else
708 | {
709 | fail |= !uint.TryParse(line.Substring(1, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out count);
710 | fail |= !uint.TryParse(line.Substring(3, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address);
711 | fail |= !byte.TryParse(line.Substring(7, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data);
712 | command = (INTEL_COMMAND)data;
713 | fail |= !byte.TryParse(line.Substring(line.Length - 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out checksum);
714 | }
715 | #endregion
716 | }
717 | else
718 | continue; // Ignore line
719 |
720 | if (fail)
721 | {
722 | Console.WriteLine(string.Format("Can't parse line {0}", lineNumber));
723 | break;
724 | }
725 |
726 | switch (command)
727 | {
728 | case INTEL_COMMAND.EOF: // End of File
729 | return 0;
730 | case INTEL_COMMAND.DATA:
731 | #region Data Record
732 | idx = 9;
733 | goto data_loop;
734 | case INTEL_COMMAND.DATA_LOOP:
735 | data_loop:
736 | for (; !fail && count > 0; --count)
737 | {
738 | if (line.Length < idx + 2)
739 | {
740 | Console.WriteLine(string.Format("Data record too short at line {0}", lineNumber));
741 | fail = true;
742 | }
743 | else
744 | fail = !byte.TryParse(line.Substring(idx, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data);
745 |
746 | if (!fail)
747 | writeToMemory(segment_address + extend_address + address - BaseAddress, data);
748 |
749 | address++;
750 | idx += 2;
751 | }
752 | break;
753 | #endregion
754 | case INTEL_COMMAND.EXT_SEGMENT_ADDR: // Extended Segment Address Record
755 | #region Extended segment address record
756 | if (count != 2 || line.Length != 15)
757 | {
758 | Console.WriteLine(string.Format("Bad Extended segment address record line {0}.", lineNumber));
759 | }
760 | else
761 | {
762 | fail |= !uint.TryParse(line.Substring(9, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out segment_address);
763 | if (fail)
764 | Console.WriteLine(string.Format("Bad Start Address records line {0}.", lineNumber));
765 | else
766 | segment_address <<= 4;
767 | }
768 | break;
769 | #endregion
770 | case INTEL_COMMAND.SEGMENT_ADDR:
771 | #region Start Segment Address Record
772 | if (count != 4)
773 | {
774 | Console.WriteLine(string.Format("Bad Start Segment records line {0}.", lineNumber));
775 | }
776 | else
777 | {
778 | fail |= !uint.TryParse(line.Substring(9, 8), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out start_address);
779 | if (fail)
780 | Console.WriteLine(string.Format("Bad Start Segment records line {0}.", lineNumber));
781 | else
782 | Console.WriteLine(string.Format("Start Segment: {0:X}", start_address));
783 | }
784 | break;
785 | #endregion
786 | case INTEL_COMMAND.EXTEND_ADDR:
787 | #region Extended Linear Address Record
788 | if (line.Length != 15)
789 | {
790 | Console.WriteLine(string.Format("Bad Extended Address records line {0}.", lineNumber));
791 | fail = true;
792 | }
793 | else
794 | {
795 | fail |= !uint.TryParse(line.Substring(9, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out extend_address);
796 | if (!fail)
797 | extend_address = extend_address << 16;
798 | }
799 | break;
800 | #endregion
801 | case INTEL_COMMAND.LINEAR_ADDR:
802 | #region Start Linear Address Record
803 | if (count != 4)
804 | {
805 | Console.WriteLine(string.Format("Bad Linear Address record line {0}.", lineNumber));
806 | }
807 | else
808 | {
809 | fail |= !uint.TryParse(line.Substring(9, 8), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out linear_address);
810 | if (fail)
811 | Console.WriteLine(string.Format("Bad Linear Address record line {0}.", lineNumber));
812 | else
813 | Console.WriteLine(string.Format("Linear Address: 0x{0:X}", linear_address));
814 | }
815 | break;
816 | #endregion
817 | default:
818 | Console.WriteLine(string.Format("Bad command {0} at line {1}.", command, lineNumber));
819 | fail = true;
820 | break;
821 | }
822 | if (fail)
823 | break;
824 | }
825 | }
826 | return fail ? 1 : 0;
827 | }
828 | #endregion
829 |
830 | #region writeToMemory(uint address, byte data)
831 | private static void writeToMemory(uint address, byte data)
832 | {
833 | if (address < MemoryLow || address >= MemoryHigh)
834 | {
835 | uint block = address / BLOCK_SIZE;
836 | uint low = Math.Min(MemoryLow, block * BLOCK_SIZE);
837 | uint high = Math.Max(MemoryHigh, (block + 1) * BLOCK_SIZE);
838 | uint idx;
839 | if (Memory == null)
840 | {
841 | Memory = new byte[high - low];
842 | MemoryLow = low;
843 | idx = MemoryLow;
844 | }
845 | else
846 | {
847 | byte[] memory = new byte[high - low];
848 | Memory.CopyTo(memory, MemoryLow - low);
849 | Memory = memory;
850 | idx = low;
851 | while (idx < MemoryLow)
852 | Memory[idx++ - low] = EmptyValue;
853 | MemoryLow = low;
854 | idx = MemoryHigh;
855 | }
856 | while (idx < high)
857 | Memory[idx++ - low] = EmptyValue;
858 | MemoryHigh = high;
859 | }
860 | AddressMax = Math.Max(AddressMax, address);
861 | AddressMin = Math.Min(AddressMin, address);
862 | Memory[address - MemoryLow] = data;
863 | }
864 | #endregion
865 | }
866 | }
867 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Hex2Bin")]
9 | [assembly: AssemblyDescription("Hex <-> Bin utility")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("X893")]
12 | [assembly: AssemblyProduct("Hex2Bin")]
13 | [assembly: AssemblyCopyright("Copyright X893 © 2013")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("a8e1f500-e5ba-4b30-8cc4-b8e322081404")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Hex2Bin
2 | =======
3 |
4 | Hex <-> Bin conversion utility
5 | Also can process Microchip JAM file - multiple hex files.
6 |
--------------------------------------------------------------------------------
/bin/Debug/Hex2Bin.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x893/Hex2Bin/6d6631958b65cd46fad4395aa027abee4c42dc2c/bin/Debug/Hex2Bin.exe
--------------------------------------------------------------------------------