Romhacking.net

Romhacking => Programming => Topic started by: DarkSamus993 on March 07, 2016, 05:18:09 PM

Title: C++ Read bytes from a binary file and store them as a variable?
Post by: DarkSamus993 on March 07, 2016, 05:18:09 PM
I'm working on writing a decompression utility for Mega Man X4-6 (http://www.romhacking.net/forum/index.php/topic,21330.0.html) and I can't seem to find information on how to read bytes from a binary file and store them as a variable (little endian, because that's what the PSX uses). I'm coding in C++ (just a simple console app) and this is to emulate the MIPS instruction LHU (Load Half-Word Unsigned = 16 bits). I also need to do the converse and store a half-word.

The necessary R3000 registers for the decompression routine are stored as variables of the same name. The user supplies the name of the input/output files and the address (hex) to start reading data from the input file.

For example:
MIPS: lhu    t1, $0000(a0)    =    t1 = memory[a0 + $0000]     =    Compressed data is loaded into t1 from address a0.
C++ : go to input file offset from variable a0 and read 16 bits (little endian) and store  into variable t1.

MIPS: sh     v0, $0000(a1)    =    memory[a1 + $0000] = v0    =    Uncompressed data is stored at address a1 from v0.
C++ : go to output file offset from variable a1 and write 16 bits (little endian) from variable v0.

Can someone give me some code examples on how this would work?
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: Gemini on March 07, 2016, 05:43:44 PM
Easier solution: store the whole input as a buffer, same for the output, and typecast both buffers as unsigned short values, then simply write and read like a byte array.
Hipster solution: use buffers again, but access them with something like *(unsigned short*)&buffer[pos].
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: RyanfaeScotland on March 07, 2016, 05:51:48 PM
Where have you searched and what have you found so far? I assume you've googled it but I googled c++ read binary file (https://www.google.co.uk/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=c%2B%2B%20read%20binary%20file) and got a lot of good results so it would be handy to narrow it down a little!
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: tvtoon on March 07, 2016, 06:30:02 PM
"How can I open a stream in binary mode?" (https://isocpp.org/wiki/faq/input-output) Save yourself for later requests. ;)
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: Disch on March 07, 2016, 06:45:07 PM
Quote from: Gemini on March 07, 2016, 05:43:44 PM
Easier solution: store the whole input as a buffer, same for the output, and typecast both buffers as unsigned short values, then simply write and read like a byte array.
Hipster solution: use buffers again, but access them with something like *(unsigned short*)&buffer[pos].

Note that this solution will only work if the machine you're running on has the same endianness as the file expects.  Most machines now are little endian so this is "mostly safe" -- but mostly isn't enough for me and I don't recommend it be enough for you.

Golden rule is never data from a binary file in chunks that are any larger than a single byte.  Assemble larger types from individual bytes yourself.  Yeah it takes 10 extra lines of code, but big whoop.
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: BlackDog61 on March 08, 2016, 02:15:04 PM
i happened to have these at hand, so here's lazy time:

int openBinFile(fstream &myfile, const char *myfile_name) {
myfile.open (myfile_name, ios::in|ios::out|ios::binary );
if (false == myfile.is_open()) {
cout << "Error opening " << myfile_name << "\n";
return 2;
} else {
cout << "File " << myfile_name << " has been opened OK.\n";
return 0;
}
}



fstream in_file;
// open it up with previous function, then
char file_data;
in_file.read((char*)(&file_data), sizeof(char));

I let file_data in a single byte as per Ditch's comment, so you need to iterate on this.
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: Gemini on March 08, 2016, 03:08:10 PM
Quote from: Disch on March 07, 2016, 06:45:07 PMNote that this solution will only work if the machine you're running on has the same endianness as the file expects.  Most machines now are little endian so this is "mostly safe" -- but mostly isn't enough for me and I don't recommend it be enough for you.
I doubt endianness is really a problem unless user is a dummy; x86-64 and r3000 are endian-compatible, so there's no harm unless you're using some crappy Motorola CPU from the early 90's.
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: DarkSamus993 on March 08, 2016, 09:16:18 PM
Thanks guys! You've given me some good insight on how to handle this situation. I started learning MIPS assembly and C++ roughly three weeks ago, so everything for this project is new territory for me. As such, I've been doing a lot of reading and happen to stumble upon this article (http://www.cplusplus.com/articles/DzywvCM9/) which describes exactly what Disch is talking about. Hopefully, I can implement something similar.
Title: Re: C++ Read bytes from a binary file and store them as a variable?
Post by: henke37 on March 15, 2016, 08:15:30 AM
Find a library that wraps the stream and provides handy member functions like setEndian and readU32.