I have the following parts of C# Code for example and other else if's, where input_byte == have different Hex Values after the == :-
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;
With the If and Else If parts of the code i.e. input_byte == 0xFF 0xFE 0xFD etc.. I want to alter the code, so I can brute force all possible combinations of individual hex values.
I think from 0x00 to 0xFF that is either 255 or 256 hex values. For example instead of 0xFF it could be 0x6E instead of 0xFE it be 0xFA etc. I have tried altering input_byte == to different things in the hope I get something useful as an output image. This code was used on another DOS game, to save graphics images as greyscale bitmap images.
I using this on the previous DOS game in the series.
I was thinking of using:
For(int input_byte=0x00;
input_byte <= 0xFF;
input_byte++)
Somewhere in the code, but I don't think that would do all possible combinations of hex values.
I have Added the following to my Code :-
for (int i = 0x00; i <= 0xFF; input_byte++)
After
input_byte = input_data[current_input_position];
current_input_position++;
And changed all input_byte ==
to input_byte == 0x00
And removed a line of Code, that saves Files other than .bmp's, so only .bmp's are saved, have I done the write thing here ? As I am not sure.
The unpac Program is still running after 30 minutes. So possibly I have made the correct amendments ?
I have changed to using this line of Code instead :-
for (int i = 0x00; i <= 0xFF; ++input_byte)
From :-
for (int i = 0x00; i <= 0xFF; input_byte++)
After reading up some Stackoverflow posts, of what the differences are, between ++i and i++, the amended line of Code sounds more appropriate for what I want, I hope this brute forcing, method takes hours rather than much longer. Can someone clarify for me, if all the changes I have made to my C# Code, definately should work ?
I didn't get anywhere, with the above for loop, and I tried doing it the other way round i.e :-
for (int i = 0xFF; i >= 0x00; --input_byte)
or :-
for (int i = 0xFF; i >= 0x00; i = --input_byte)
i.e. working backwards, so changing all the five input_byte == 0x00 to input_byte == 0xFF.
When I run in either direction, the number in the brackets in the output in Command Prompt stays at (639) when going 0x00 to 0xFF, and (636) when it is the other way round. And the File Number just keeps going up and up. Whereas for other Ranges, I have tried small or large, i.e. loop from 0x00 to 0x01 but even as far as 0x00 to 0xFE, the number in the brackets changes, for each File output, and the Program runs for a few seconds. for either large or small ranges in the for loop, when I use :-
i = --input_byte
or :-
i = ++input_byte
Whereas if I use 0xFF, it goes on and on. The other hex value ranges small or large, do the same when I just use ++input_byte or --input_byte. I was getting the same outcomes when it was input_byte++ or input_byte--. I could really do with some help here, if that is okay ?
Could someone suggest, where I am going wrong with this, and what
changes, I need to make to my Code ?
Also how do I get the for loop, not to include all combinations of Hex Values that are numbers only ? As I know, these combinations won't produce saved .bmp Files.
i.e. all input bytes == are numbers only for each of the 5 input_byte == blocks of Code ? i.e both digits are numbers i.e. 00, 01 etc ?
Please can someone help me ?
Regards
Eddie Winch
Related
In C/C++ you could do this O(n) with a pointer to a buffer and casting to 32bit datatype, but in C# given byte[] or IEnumerable<byte> and an int32 how might you efficiently find the first position of the DWORD in the byte buffer, ideally using built-in library methods?
I don't want to venture into unsafe code so I can of course search for a 4-element byte sub-buffer. But is there a neater way to take advantage of my search value being 32bits long?
Trivial workup (pseudo-ish):
int Find(IEnumerable<byte> buf, int val)
{
byte d = val & 0xff, c = (val >>8) & 0xff, b = (val >>16) & 0xff, a = (val>>24) & 0xff;
for(int i=0;i<buf.Length - 3;++i)
{
if(buf[i] == d && buf[i+1] == c && buf[i+2] == b && buf[i+3] == a)
return i
}
return -1;
}
Basically wondering if I can combine all 4 byte-wise checks with a single 32-bit check.
wondering if I can combine all 4 byte-wise checks with a single 32-bit check
Not without violating alignment. Some options you do have are:
a masked 32-bit comparison against the first part of the value for each of the 4 possible alignments (this will be testing 32, 24, 16, or 8 bits). After you get a success, you'll still have to test against the remaining bits
A SIMD comparison looking for the first byte (or most unique -- I certainly wouldn't want to search for 0x00 since there will be far more than 0.5% false positives) of the needle at 16 or so possible adjacent locations simultaneously. Once you get a match you need to test the three following bytes also.
So the following code runs through all values in a byte (0-255) and prints values that fit in the specified bit mask. Normally this wouldn't be a problem (since a regular "value & mask" only checks for set bits), but since I want to ignore some bits and make sure some are zero, the code that checks for that, ended up seeming a little long and not efficient.
I'll explain a little more details on the code.
The bit mask I used to test the code is the following: 0-1--10-
Dashes mean bits that are ignored. To find what bits should be ignored I split the mask in code into two separate masks. The first one is "mask" variable, which holds the bits that should be set. The second mask "ignore" has the bits cleared that should be ignored. This way the code can distinguish a cleared bit from one to ignore in "mask". The values I used are 00100100 (36) for mask and 10100110 (166) for ignore.
The code does correctly return expected values:
0x24
0x25
0x2C
0x2D
0x34
0x35
0x3C
0x3D
0x64
0x65
0x6C
0x6D
0x74
0x75
0x7C
0x7D
Is there any way to make this code more efficient and possibly even have just one mask to test the value with?
private void button1_Click(object sender, EventArgs e)
{
byte mask = (byte)(Int32.Parse(textBoxMask.Text));
byte ignore = (byte)(Int32.Parse(textBoxIgnore.Text));
ushort i = 0;
byte val;
while(i <= 0xFF)
{
val = (byte)i;
if (((val & ignore & mask) == mask) && ((~(val) & ~(mask) & ignore) == (~(mask) & ignore)))
{
Console.WriteLine(string.Format("{0:X}", val));
}
i++;
}
}
if ((val & ignore) == mask)
...gives the same output.
I think your terminology might have been making this more seem more complicated. ignore should be called mask because you're using it to mask out (with zeroes) the bits in val that are unimportant. What you're calling mask is the expected result of that operation.
byte expected = 0b_0010_0100; // was mask
byte mask = 0b_1010_0110; // was ignore
// ...
if ((val & mask) == expected)
As for being more efficient, this a negligible optimization in terms of execution but it's a big improvement in readability/comprehension. I'm not familiar with any techniques that would allow you to get rid of the loop, especially if you're accepting values from the user, so I'm thinking this is about as good as you're going to get.
Alright so here goes.
I currently need to write an extension method for the System.IO.BinaryReader class that is capable of reading a specific format.
I have no idea what this format is called but I do know exactly how it works so i will describe it below.
Each byte that makes up the value is flagged to indicate how the reader will need to behave next.
The first byte has 2 flags, and any subsequent bytes for the value have only 1 flag.
First byte:
01000111
^^^^^^^^
|||____|_ 6 bit value
||_______ flag: next byte required
|________ flag: signed value
Next bytes:
00000011
^^^^^^^^
||_____|_ 7 bit value
|________ flag: next byte required
The first byte in the value has 2 flags, the first bit is if the value is positive or negative.
The second bit is if another byte needs to be read.
The 6 remaining bits is the value so far which will need to be kept for later.
If no more bytes need to be read then you just return the 6 bit value with the right sign as dictated by the first bit flag.
If another byte needs to be read then you read the first bit of that byte, and that will indicate if another byte needs to be read.
The remaining 7 bits are the value here.
That value will need to be joined with the 6 bit value from the first byte.
So in the case of the example above:
The first value was this: 01000111.
Which means it is positive, another byte needs to be read, and the value so far is 000111.
Another byte is read and it is this: 00000011
Therefore no new bytes need to be read and value here is this: 0000011
That is joined onto the front of the value so far like so: 0000011000111
That is therefore the final value: 0000011000111 or 199
0100011100000011 turns into this: 0000011000111
Here is another example:
011001111000110100000001
^^^^^^^^^^^^^^^^^^^^^^^^
| || ||______|_____ Third Byte (1 flag)
| ||______|_____________ Second Byte (1 flag)
|______|_____________________ First Byte (2 flags)
First Byte:
0 - Positive
1 - Next Needed
100111 - Value
Second Byte:
1 - Next Needed
0001101 - Value
Third Byte:
0 - Next Not Needed
0000001 - Value
Value:
00000010001101100111 = 9063
Hopefully my explanation was clear :)
Now i need to be able to write a clear, simple and, and most importantly fast extension method for System.IO.BinaryReader to read such a value from a stream.
My attempts so far are kind of bad and unnecessarily complicated involving boolean arrays and bitarrays.
Therefore I could really do with somebody helping me out with this in writing such a method, that would be really appreciated!
Thanks for reading.
Based on the description in the comments I came up with this, unusually reading in signed bytes since it makes the continue flag slightly easier to check: (not tested)
static int ReadVLQInt32(this BinaryReader r)
{
sbyte b0 = r.ReadSByte();
// the first byte has 6 bits of the raw value
int shift = 6;
int raw = b0 & 0x3F;
// first continue flag is the second bit from the top, shift it into the sign
sbyte cont = (sbyte)(b0 << 1);
while (cont < 0)
{
sbyte b = r.ReadSByte();
// these bytes have 7 bits of the raw value
raw |= (b & 0x7F) << shift;
shift += 7;
// continue flag is already in the sign
cont = b;
}
return b0 < 0 ? -raw : raw;
}
It can easily be extended to read a long too, just make sure to use b & 0x7FL otherwise that value is shifted as an int and bits would get dropped.
Version that checks for illegal values (an overlong sequence of 0xFF, 0xFF... for example, plus works with checked math of C# (there is an option in the C# compiler to use cheched math to check for overflows)
public static int ReadVlqInt32(this BinaryReader r)
{
byte b = r.ReadByte();
// the first byte has 6 bits of the raw value
uint raw = (uint)(b & 0x3F);
bool negative = (b & 0x80) != 0;
// first continue flag is the second bit from the top, shift it into the sign
bool cont = (b & 0x40) != 0;
if (cont)
{
int shift = 6;
while (true)
{
b = r.ReadByte();
cont = (b & 0x80) != 0;
b &= 0x7F;
if (shift == 27)
{
if (negative)
{
// minumum value abs(int.MinValue)
if (b > 0x10 || (b == 0x10 && raw != 0))
{
throw new Exception();
}
}
else
{
// maximum value int.MaxValue
if (b > 0xF)
{
throw new Exception();
}
}
}
// these bytes have 7 bits of the raw value
raw |= ((uint)b) << shift;
if (!cont)
{
break;
}
if (shift == 27)
{
throw new Exception();
}
shift += 7;
}
}
// We use unchecked here to handle int.MinValue
return negative ? unchecked(-(int)raw) : (int)raw;
}
I am trying to print each byte in an array (Byte Array) using a for loop. However since I am using the String.Format, it converts the 0x00 in the byte array to a 0. How can I print it as 00.
Trace.Write("\n--->");
for (int K = 1; K <= j; K++)
Debug.Write(string.Format("{0:X}", FrameByteArray[K]));
I know it should be simple, but I have a hard time figuring it out.
Please advice.
Just use {0:X2} instead - this will ensure the number will always have at least two characters.
I have a byte array in c#. I need to pull out a certain number of bytes starting at a bit position that may not lie on a byte boundary.
Write a little helper method which uses the shift operators to get a byte out
e.g.
byte[] x = new[] {0x0F, 0xF0}
result = x[0] << 4 | x[1] >> 4;
returns 8 bits from the 5th bit position 0xFF
You could easily vary the position using the modulo operator %
a byte is the minimal alignment you can read with the standard stream readers in .NET
If you want to read bits, you need to use bitwise operators and masks to determine if a bit is on (1) or off (0).
But, this means you could use boolean true/false to tell what the contents of a byte are. One way is to read the bits into a boolean enumeration. Something like this extension method could work:
public static IEnumerable<bool> BitsToBools(IEnumerable<byte> input)
{
int readByte;
while((readByte = input.MoveNext()) >= 0)
{
for(int i = 7; i >= 0; i--) // read left to right
yield return ((readByte >> i) & 1) == 1;
}
}
You could add a startIndex and a count to the extension method if you want, or pass in the range from the calling method.