Search code examples
c++file-iohexemulationhexdump

Reading file in hex gives wrong output (skips some hex values)


I'm trying to read/print out the hex instructions from the Chip8 version of Pong (which can be downloaded here).
Here is the code I am using to read in ROM:

//Open ROM
string dir = "Test/PONG";
ifstream inf(dir.c_str(), ios::binary);

unsigned char input;
for(int i = 0; inf >> input; i++) {
    //Each loop prints 1 bytes
    //New line every 16 bytes and print line number
    if(i%16 == 0) {
        cout << endl;
        cout << setw(7) << setfill('0') << i << " ";
    }
    //2 extra spaces after 8 bytes
    else if(i%8 == 0)
        cout << "  ";
    cout << hex << setw(2) << setfill('0') << (int)input << " ";
}
cout << endl;

And here's part of the output:

0000000 6a 02 6b 6c 3f 6d a2 ea   da b6 dc d6 6e 00 22 d4  
0000010 66 03 68 02 60 60 f0 15   f0 07 30 00 12 1a c7 17  
0000020 77 08 69 ff a2 f0 d6 71   a2 ea da b6 dc d6 60 01  

...

And here's the output that I believe is correct which I got from running the command "hexdump -C PONG" in the terminal:

00000000  6a 02 6b 0c 6c 3f 6d 0c  a2 ea da b6 dc d6 6e 00  
00000010  22 d4 66 03 68 02 60 60  f0 15 f0 07 30 00 12 1a  
00000020  c7 17 77 08 69 ff a2 f0  d6 71 a2 ea da b6 dc d6  

...

On the first line of hex values, you can see the value '0c' twice in terminal but the output of the code skips printing '0c'. I'm not sure why my code is skipping '0c'. Am I reading the file improperly? Is the command "hexdump" providing the wrong output? What can I change about the way I read the file?

EDIT: Using inf.get(input) is able to read in '0c' however it also outputs some hex values differently.
For example:

6a 02 6b 0c 6c 3f 6d 0c ffffffa2 ffffffea ffffffda ffffffb6 ffffffdc ffffffd6 6e 00 22 ffffffd4 66 03 68 02 60 60 fffffff0

EDIT 2: The 'f's are printed since some hex values are read as negative numbers. So I made an if statement that checks if input is negative, if it is negative I multiply it by -1 then print the hex value.

EDIT 3: I decided to use a stringstream to only print out the last 2 characters for negative hex values:

stringstream convert;
if((int)input < 0) {
     convert << hex << (int)input;
     cout << convert.str().substr(6,8) << " ";
     convert.str("");
}

EDIT 4: The hex '0c' represents the escape sequence '\f' and is therefore ignored when printing. Using inf.get(input) instead of inf >> input stores characters into input as unformatted characters (I think). However the get() function can't take a unsigned char as an argument. So I have to cast input to char&.
In conclusion, I had to change inf >> input to inf.get((char&)input).

Source: http://www.cplusplus.com/reference/istream/istream/get/


Solution

  • Operator>> reads formatted data (char in your case) from the input stream, so a char with value 12 (0c in hex) is considered as ASCII form feed and ignored ( as a value of 32 or 0x20 would be considered a space ). Char are also signed values and an hex value of a2 (which is decimal 162) would be stored as a negative value. Promoting that value to an int would keep the sign and due to complementation, when printed as unsigned you'll get the ffff's.

    keep the

    unsigned char input;
    

    then to read the values use

    inf.get(static_cast<char>(input))
    

    and to print

    cout << hex << setw(2) << setfill('0') << static_cast<unsigned int>(input) << " ";