Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
I have the following C# Code :-

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;


namespace Unpac {
	class Program {

		//_____________________________________________________________________
		static string		input_filename_no_ext;
		static int			current_output_index;
		static string		output_directory;
		static List<byte>	output_buffer;
		static int			image_height;
		static int			line_min_length;
		static int			line_max_length;

		//_____________________________________________________________________
		static void Main(string[] args) {

			int?		forced_image_width;
			string		input_fullpath;
			string		input_directory;
			string		input_filename;
			byte[]		input_data;
			long		input_max_valid_position;
			long		current_input_position;
			byte		input_byte;
			byte		RLE_sumador;
			int			count;
			byte		b;
			int			n;
			bool		RLE_FC_swap;
			byte		b2;
			int			width_current;


			if(args.Length<2) {
				Console.WriteLine("Use: unpac.exe <InputFile.pac> <OutputDir> [ImageWidth]");
				return;
			}

			if(args.Length>2) {
				forced_image_width = int.Parse(args[2]);
			} else {
				forced_image_width = null;
			}
			
			try {
				input_fullpath		= Path.GetFullPath(args[0]);
				input_directory		= Path.GetDirectoryName(input_fullpath);
				input_filename		= Path.GetFileName(input_fullpath);

				input_fullpath		= Path.Combine(input_directory, input_filename);
				if(!File.Exists(input_fullpath)) throw new Exception();

				int p = input_filename.LastIndexOf('.');
				if(p==-1) {
					input_filename_no_ext = input_filename;
				} else {
					input_filename_no_ext = input_filename.Substring(0, p);
				}

			} catch {
				Console.WriteLine("ERROR: invalid input file");
				return;
			}

			try {
				output_directory = Path.GetFullPath(args[1]);
				if(!Directory.Exists(output_directory)) {
					Directory.CreateDirectory(output_directory);
				}
			} catch {
				Console.WriteLine("ERROR: invalid output directory");
				return;
			}

			try {
				input_data = File.ReadAllBytes(input_fullpath);
			} catch {
				Console.WriteLine("ERROR: cannot read from input file");
				return;
			}

			Console.WriteLine($"{input_filename}");

			input_max_valid_position	= input_data.Length - 1;
			current_input_position		= 0;
			current_output_index		= 1;
			output_buffer				= new List<byte>();

			RLE_sumador					= 0;
			line_min_length				= int.MaxValue;
			line_max_length				= 0;
			width_current				= 0;
			image_height				= 0;

			while(current_input_position <= input_max_valid_position) {

				input_byte = input_data[current_input_position];
				current_input_position++;

				if(input_byte == 0xFF) {
					//==============
					// Fin de chunk
					//==============
					Save();
					current_output_index++;

					RLE_sumador			= 0;
					line_min_length		= int.MaxValue;
					line_max_length		= 0;
					width_current		= 0;
					image_height		= 0;

				} else if(input_byte == 0xFE) {
					//=================
					// Siguiente linea
					//=================
					if(width_current < line_min_length) line_min_length = width_current;
					if(width_current > line_max_length) line_max_length = width_current;

					if(forced_image_width!=null) {
						count = forced_image_width.Value - width_current;
						if(count > 0) {
							for(n=0; n<count; n++) {
								output_buffer.Add(0);
							}
						}
					}

					image_height++;
					width_current = 0;

				} else if(input_byte == 0xFD) {
					count = (int) (input_data[current_input_position]) + 1;
					current_input_position++;

					b = input_data[current_input_position];
					current_input_position++;

					for(n=0; n<count; n++) {
						output_buffer.Add(b);
					}

					width_current += count;

				} else if(input_byte == 0xFC) {
					b = input_data[current_input_position];
					current_input_position++;

					b2 = (byte)(b + 1);

					count = (int) (input_data[current_input_position]) + 1;
					current_input_position++;

					RLE_FC_swap = false;
					for(n=0; n<count; n++) {
						output_buffer.Add(
							RLE_FC_swap ? b2 : b
						);
						RLE_FC_swap = !RLE_FC_swap;
					}

					width_current += count;

				} else if(input_byte == 0xFB) {
					RLE_sumador = input_data[current_input_position];
					current_input_position++;

				} else {
					b = (byte)(input_byte >> 2);
					b += RLE_sumador;
					count = (input_byte & 3) + 1;

					for(n=0; n<count; n++) {
						output_buffer.Add(b);
					}

					width_current += count;
				}
			}

			Save();
		}

		//_____________________________________________________________________
		static void Save() {

			if(output_buffer.Count == 0) return;

			string	output_filename;
			string	output_fullpath;
			byte[]	output_array;
			int		output_length;
			bool	is_valid_image;


			output_filename	= $"{input_filename_no_ext}.{current_output_index:D3}";
			output_fullpath	= Path.Combine(output_directory, output_filename);
			output_array	= output_buffer.ToArray();
			output_length	= output_array.Length;
			is_valid_image	= false;


			if(image_height > 0) {
				if(line_min_length != line_max_length) {
					Console.WriteLine($" -> {output_filename} ({output_length}) (min width:{line_min_length}) (max width:{line_max_length}) (height:{image_height})");
				} else {
					Console.WriteLine($" -> {output_filename} ({output_length}) (width:{line_min_length}) (height:{image_height})");
					is_valid_image = true;
				}
			} else {
				Console.WriteLine($" -> {output_filename} ({output_length})");
			}

			try {
				if(is_valid_image) {
					Bitmap.Save(output_fullpath + ".bmp", output_array, line_min_length, image_height);
				} else {
					File.WriteAllBytes(output_fullpath, output_array);
				}
			} catch {
				Console.WriteLine("ERROR: cannot save to output file");
			}

			output_buffer.Clear();
		}

	}
}


How can I code in C# to try the Hex values, 0x00 to 0xFF in this code for input_byte == , i.e what should I type in the posted Code, to try the range each hex value in turn ? I looked on the internet about ranges in c# but I didn't find anything suitable, to help me with. Any help would be much appreciated Regards Eddie Winch

What I have tried:

I have tried altering the input_byte values. But I need to be able, to try all possible combineations, of all individual Hex Values i.e. there are either 255 or 256. Where it says input_byte == in the Code. I wrote, and also copy and pasted 4x256, else if Statements in my latest modification, of my Program.cs Code. But I don't Think the Compiled Program, is doing what I wan't to achieve.

I asked a person who has a knowledge of C# he said maybe I could try the following in a for loop ? :-

C#
for(int nSomething=0; nSomething<256: n++) { doSomething(nSomething);}


Could someone suggest a modification I could make, to my original Code, using the above C# code, to achieve what I want ? obviously the Something would be replaced with other text ?

Here a a few lines, of the 4x256 else if Statements in my Code :-

C#
if (input_byte == 0x00)
                  {
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;
                    }
                 else if (input_byte == 0x01)
                    { 
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;

                }
                else if (input_byte == 0x02)
                {
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;

                }
                else if (input_byte == 0x03)
                {
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;

                }
                else if (input_byte == 0x04)
                {
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;

                }
                else if (input_byte == 0x05)
                {
                    //==============
                    // Fin de chunk
                    //==============
                    Save();
                    current_output_index++;

                    RLE_sumador = 0;
                    line_min_length = int.MaxValue;
                    line_max_length = 0;
                    width_current = 0;
                    image_height = 0;


C#
if (input_byte == 0x00)
                {    //=================
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;

                 }
                 else if (input_byte == 0x01)
                 {
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;

                 }
                 else if (input_byte == 0x02)
                 {
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;

                 }
                 else if (input_byte == 0x03)
                 {
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;

                 }
                 else if (input_byte == 0x04)
                 {
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;

                 }
                 else if (input_byte == 0x05)
                 {
                     // Siguiente linea
                     //=================
                     if (width_current < line_min_length) line_min_length = width_current;
                     if (width_current > line_max_length) line_max_length = width_current;

                     if (forced_image_width != null)
                     {
                         count = forced_image_width.Value - width_current;
                         if (count > 0)
                         {
                             for (n = 0; n < count; n++)
                             {
                                 output_buffer.Add(0);
                             }
                         }
                     }

                     image_height++;
                     width_current = 0;


etc
Posted
Updated 12-Nov-22 8:05am
v7
Comments
Member 15627495 31-Oct-22 13:14pm    
hello,
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/selection-statements

why don't you use case/break to achieve instead of if elseif elseif ( hard writing and hard reading )



https://www.techiedelight.com/fr/conversion-between-integer-and-hexadecimal-csharp/

Use a switch block:
C#
switch (input_byte)
{
case 0xFF:
// code for FF
    break;
case 0xFE:
// code for FE
    break;
case 0xFD:
// code for FD
    break;
default:
// code for all other values
    break;
}


[edit]
Added the break statements; thanks OG.
[/edit]
 
Share this answer
 
v2
To add to what Richard says, you will also need break statements at the end of each set of case code:
C#
switch (input_byte)
    {
    case 0xFF:
        ... code for FF...
        break;
    case 0xFE:
        ... code for FE ...
        break;
    case 0xFD:
        ... code for FD ...
        break;
    default:
        ... code for all other values ...
        break;
    }
 
Share this answer
 
Comments
Eddie Winch 31-Oct-22 14:11pm    
Hi Guys, Many thanks for your very helpful reply's, it is very much appreciated.

So are you saying, it is not possible to do a range line of Code, i.e instead of typing each hex value out, specify trying each one in a range ?
OriginalGriff 31-Oct-22 14:32pm    
The problem is that you do different things for each different hex value in your code sample: so "ranging" them isn't exactly going to work.

If you want to test all possible values then why not just use a for loop?
Eddie Winch 31-Oct-22 14:44pm    
Hi OriginalGriff, I would like to Test all possible hex values for the Fin de chunk, part of the code instead of 0xFF, I could look into a For loop, this Code was written for me, I am okay at adapting Code.
Eddie Winch 31-Oct-22 14:52pm    
The reason I wanted, to try all possible Hex Values, is this is one of two Codes extracting Images from a DOS Games Graphics, and saving it as a bitmap, it is to do with RLE, I have had some images saved but they are not a full image, this code worked for another game but not for this one. This game is the previous game by the same company, so I was hoping the RLE was the same. But want to try all the combinations of Hex Values, in case I get a proper .bmp image saved you see.
Eddie Winch 31-Oct-22 15:05pm    
Hi FreedMalloc, Could you post your comment again ? It is missing now, for some reason ?

I am not sure why you are using hex notation in your code. A 2 letter hex figure is simply a byte expressed in base 16 format. It is useful when using bit operatives because it displays a byte as 2 four bit nibbles. There is a technique for selecting a range that may help you. It uses a list of Func delegates that return an isHandled bool. Something along these lines.

C#
//construct a list to hold the required functions
 List<Func<int, int, bool>> list = new();
//an example function that can be  added to the list
private bool HandleA(int highRange, int lowRange)
           {
                 if(highRange<=int.MaxValue && lowRange >=75)
                  {
                  //do something
                  Console.WriteLine("Handled A");
                  return true;
                  }
                //let the next delegate try to handle it
                return false;

           }
//Iterate over the list until one of the functions is able to
//handle the parameters
 int h=77;
 int l=75;
              foreach (var func in list)
                {
                    if (func(h, l) == true)
                    {
                        Console.WriteLine($"Handled {h} {l}");
                        break;
                    }

                }

 
Share this answer
 
Comments
Eddie Winch 1-Nov-22 18:22pm    
What do I need to change in my Code, to try all combinations, of possible Hex Values in each of input_bytes code, for my Code ? i.e. all combinations for each individual input byte, there are 255 or 256 valid hex Values 0x00 to 0xFF ?
Would this work for these parts of code for example ? :-

C#
<pre>switch(input_byte)
				{
					case when (input_byte >= 0x00 && input_byte <= 0xFF): 
					//==============
					// Fin de chunk
					//==============
					Save();
					current_output_index++;

					RLE_sumador			= 0;
					line_min_length		= int.MaxValue;
					line_max_length		= 0;
					width_current		= 0;
					image_height		= 0;
					break;

				case when (input_byte >= 0x00 && input_byte <= 0xFF):
					//=================
					// Siguiente linea
					//=================
					if(width_current < line_min_length) line_min_length = width_current;
					if(width_current > line_max_length) line_max_length = width_current;

					if(forced_image_width!=null) {
						count = forced_image_width.Value - width_current;
						if(count > 0) {
							for(n=0; n<count; n++) {
								output_buffer.Add(0);
							}
						}
					}

					image_height++;
					width_current = 0;
                    break;
 
Share this answer
 
v2
Comments
Richard Deeming 2-Nov-22 5:10am    
No, because your syntax is not valid C#, even in the latest language version: Selection statements - C# reference | Microsoft Learn[^]

Instead of:
case when (input_byte >= 0x00 && input_byte <= 0xFF):

you would need to use:
case >= 0x00 and <= 0xff:

But even then, your two case statements are for the same range of values, so you'd get a CS8120 compiler error.
Eddie Winch 2-Nov-22 11:51am    
Hi Richard Deeming, god how embarrasing, I can't believe I didn't work that out, both sides of that code mean the same. I would have been better, using input_byte >= 0x00 although that wouldn't work either. Many thanks for your comment, it's much appreciated.
Eddie Winch 2-Nov-22 14:17pm    
Could someone, tell me what to put, and or change in the the Code I posted, to try all combinations of Hex values, i.e. for each individual input_byte == for 0x00 to 0xFF ? Each input_byte 0x00 to 0xFF, is only on it's own in input_byte == not multiples. I would really appreciate it, if someone could tell me. Eddie Winch ))
Eddie Winch 3-Nov-22 13:17pm    
Can anyone help me ?
Hi there, I do understand the logic, and how to do switch Statements, but with 256 possible Hex Values all the combinations, of individual input_byte == would take a very along time to write. Can anyone help me, with a quicker way to do this ? Any help would be much appreciated.
 
Share this answer
 
v3
Comments
Richard MacCutchan 7-Nov-22 15:19pm    
There is no quicker way. If you want to try all values, and they all require different handling, then this is the only way. And posting your question as a solution is not a very good way to get help. If you have additional information to add then use the Improve question link above, and add complete details in your original post.
Richard MacCutchan 7-Nov-22 16:34pm    
Well yes, but look at it this way, you can write either of these:
if (input_byte == 0x00)
{
    // process byte type 00
}
else if (input_byte == 0x01)
{
    // process byte type 01
}

// ...
else if (input_byte == 0xFE)
{
    // process byte type FE
}
else if (input_byte == 0xFF)
{
    // process byte type FF
}

or
switch (input_byte)
{
    case 0x00:
    // process byte type 00
    break;
    case 0x01:
    // process byte type 01
    break;

// ...

    case 0xFE:
    // process byte type FE
    break;
    case 0xFF:
    // process byte type FF
    break;
}
Eddie Winch 7-Nov-22 17:01pm    
Excellent, so with either way, all combinations of input_bytes, i.e. 256 Hex Values will be tested ?
Richard MacCutchan 8-Nov-22 4:05am    
Well that is up to you. I am still not 100% clear whether every byte value needs a unique piece of code or some values share the same process.
Eddie Winch 8-Nov-22 5:16am    
Hi Richard, I will type the code, for all 256 Hex Values today, and will let you know, how I get on. Many thanks, for your very helpful responses.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900