473,406 Members | 2,956 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Char* operation

Airslash
221 100+
Sorry,

couldn't come up with a better title, but here's what I'm trying to do:

I'm making a small console application that reads .pak files (they're from a game). I'm building it in steps, so I don't make errors.

Right now i'm trying to obtain the amount of files stored inside such a .pak file. This is normally done by reading the first 2 bytes from the .pak files, reversing them and then interpreting them as a header.
I'm able to read the first 2 bytes by using an fstream object (ifstream) and read 2 bytes into a char* buffer.

Now I have as question, how can I reverse the 2 bytes, and then interpret it as an integer/short. ?

I tried switching the bytes of place inside the char* (treated as array) but didn't give me the result I wanted.


example :

24 00 should be read as 00 24, and resulting in 36 as integer.
Sep 24 '08 #1
15 6629
JosAH
11,448 Expert 8TB
The two bytes are stored big endian in your file and you want them to be in little
endian order. Read those two bytes in a short int and apply the ntohs() macro
to it like this:

Expand|Select|Wrap|Line Numbers
  1. unsigned short s= /* read the first two bytes */
  2. s= ntohs(s);
  3.  
kind regards,

Jos
Sep 24 '08 #2
Airslash
221 100+
Ok, I managed to get a bit further.
Here's the code I'm currently using, it's very rough just to get the 2 bytes at the moment, nothing else:

Expand|Select|Wrap|Line Numbers
  1. int main() {
  2.     // Create a new reference to a streamreader
  3.     ifstream* mystream = new ifstream("C:\\Netts\\Florensia\\Data\\Map.pak");
  4.     // Read the first 2 bytes to check the amount of files present
  5.     char* buffer = new char[2];
  6.     mystream->read(buffer, 2);
  7.     // Cast to an short
  8.     unsigned short amount = *buffer;
  9.     // reverse the byte order
  10.     amount = ntohs(amount);
  11.     // print out the result
  12.     cout << "Amount of files in Map.pak : " << amount << endl;
  13. }
  14.  
when I compile, the ntohs() command gets highlighted with the following error:
Expand|Select|Wrap|Line Numbers
  1. C:/Users/Arne/workspace/Florensia/Debug/../main.cpp:22: undefined reference to `_ntohs@4'
  2.  
any idea what this means?
Sep 24 '08 #3
Airslash
221 100+
never mind found it :)

had to link to ws2_32.lib

but now I get as output : Amount of files in Map.pak : 9216

but it should be : Amount of files in Map.pak : 36.

is the conversion going wrong then?
Sep 24 '08 #4
donbock
2,426 Expert 2GB
The purpose of ntohs is to convert an unsigned short encoded according to "TCP/IP network byte order" to host encoding. Network byte order is most-significant byte first (also called big-endian). If host encoding matches network byte order then ... either ntohs returns the unchanged input or it performs a spurious byte swap -- check your documentation.

However, your example stated that the sequence 0x24, 0x00 should be interpreted as 0x0024 = 36. This is least-significant byte first (also called little-endian).

It is a lot less confusing if you forget about these endian terms and concentrate on your problem domain:
Expand|Select|Wrap|Line Numbers
  1. /* Convert pak-encoded 16-bit value into unsigned short */
  2. const char *paktohs(const char *pointer, unsigned short *value)
  3. {
  4.     unsigned short lowbyte, highbyte;
  5.     lowbyte = *pointer++;
  6.     highbyte = *pointer++;
  7.     *value = (highbyte << 8) | lowbyte;
  8.     return pointer;
  9. }
Sep 24 '08 #5
Airslash
221 100+
Ok I think I got it, but I cannot count on it that low endian always fits, because sometimes the second set of bytes isn't always 00. i have pak files that contain over 10k files, so sometimes it can 24 1C, and then it doesn't count anymore I suppose.


Bit new to this, I know c+++ general programming but these tidbits make it confusing sometimes.
Sep 24 '08 #6
JosAH
11,448 Expert 8TB
Bit new to this, I know c+++ general programming but these tidbits make it confusing sometimes.
As always the venom is in the nitty gritty details; stick to my reply #2 and you'll
be done, i.e. read those two bytes into a short, apply that ntohs macro to the
short and voila; just a few lines of code, no more no less.

kind regards,

Jos
Sep 24 '08 #7
donbock
2,426 Expert 2GB
Ok I think I got it, but I cannot count on it that low endian always fits, because sometimes the second set of bytes isn't always 00. i have pak files that contain over 10k files, so sometimes it can 24 1C, and then it doesn't count anymore I suppose.
It doesn't matter whether the second byte is 0. The point is that your pak file expresses 16-bit values low-byte-first. That is, the byte sequence 0x24, 0x1C corresponds to 16-bit value 0x1C24 (which equals 7204).

Assembling the bytes into the unsigned short yourself as I suggested in reply #5 means that you don't have to know whether your processor is big-endian or little-endian. That code will work on either kind of system.
Sep 24 '08 #8
Airslash
221 100+
aah ok, now it makes sense :)
I've copied your code and I'm trying to pour it into several functions now.
Maybe when it's finished i'll post the entire code online to share my .pāk reader :)
Sep 25 '08 #9
Airslash
221 100+
Ok I've been trying to pour your code into a class object so I can already partiall read the 2 bytes from the entire pak file

header
Expand|Select|Wrap|Line Numbers
  1. #ifndef PAKFILE_H_
  2. #define PAKFILE_H_
  3. #include <iostream>
  4. #include <fstream>
  5. using namespace std;
  6.  
  7. class PakFile {
  8.     public:
  9.         PakFile(char* const filename);
  10.         ~PakFile();
  11.  
  12.         char* const getFilename() const;
  13.         unsigned short* const getAmountOfFiles() const;
  14.  
  15.         void setFilename(char* const filename);
  16.  
  17.         void load();
  18.  
  19.     private:
  20.         unsigned short* amount_of_files;
  21.         char* file_name;
  22.  
  23.         void readAmountOfFiles(ifstream* fileStream);
  24. };
  25.  
  26. #endif /* PAKFILE_H_ */
  27.  
cpp file implementation
Expand|Select|Wrap|Line Numbers
  1. #include "../pakfile.h"
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <fstream>
  5. using namespace std;
  6.  
  7. PakFile::PakFile(char* const filename) {
  8.     this->setFilename(filename);
  9.     this->amount_of_files = new unsigned short();
  10. }
  11.  
  12. PakFile::~PakFile() {
  13.     delete this->file_name;
  14.     delete this->amount_of_files;
  15. }
  16.  
  17. char* const PakFile::getFilename() const {
  18.     return this->file_name;
  19. }
  20.  
  21. void PakFile::setFilename(char* const filename) {
  22.     this->file_name = filename;
  23. }
  24.  
  25. void PakFile::readAmountOfFiles(ifstream* fileStream) {
  26.     // Set the pointer of the stream to the beginning of the file.
  27.     fileStream->seekg(0, ios::beg);
  28.     // Create a buffer to read the 2 chars into
  29.     char* buffer = new char[2];
  30.     // Read the 2 bytes into the buffer
  31.     fileStream->read(buffer, 2);
  32.     // Reverse the 2 bytes
  33.     // And convert them to an unsigned short.
  34.     unsigned short lowbyte, highbyte;
  35.     lowbyte = *buffer++;
  36.     highbyte = *buffer++;
  37.     *this->amount_of_files = (highbyte << 8) | lowbyte;
  38. }
  39.  
  40. void PakFile::load() {
  41.     // Create a new stream to read through the file.
  42.     ifstream* fileStream = new ifstream(this->getFilename());
  43.     // Read the amount of files first.
  44.     this->readAmountOfFiles(fileStream);
  45. }
  46.  
  47. unsigned short* const PakFile::getAmountOfFiles() const {
  48.     return this->amount_of_files;
  49. }
  50.  
main.cpp
Expand|Select|Wrap|Line Numbers
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <fstream>
  4. #include "pakfile.h"
  5.  
  6. using namespace std;
  7.  
  8. int main() {
  9.     // create a new pakfile
  10.     PakFile* file = new PakFile("C:\\Netss\\Florensia\\Data\\Map.pak");
  11.     // Load the information
  12.     file->load();
  13.     // Print the information
  14.     cout << "Amount of files in " << file->getFilename()  << " : " << *file->getAmountOfFiles() << endl;
  15.     // delete the pointer
  16.     delete file;
  17. }
  18.  
the output is this : Amount of files in C:\Netss\Florensia\Data\Map.pak : 65480
and not 36 (bytes in the file are 24 00, so should be read as 0x0024)

have I done the part of your code wrong ?
Sep 25 '08 #10
donbock
2,426 Expert 2GB
I don't see an obvious problem with your code. Let's print out the values of lowbyte, highbyte, and amount_of_files in hexadecimal to see what's going on.
Sep 25 '08 #11
newb16
687 512MB
the output is this : Amount of files in C:\Netss\Florensia\Data\Map.pak : 65480
and not 36 (bytes in the file are 24 00, so should be read as 0x0024)

have I done the part of your code wrong ?
this->file_name - it is not necessary to prepend "this->" as it is executing inside member function.
Second, why amount_of_files is pointer to integer? There is no need to do it, plain int will be enough. Next, did you try to debug ( debugprint ) it and check values of lowbyte and highbyte right after read operation - were they corrupted right there or later? Were the data actually read from the stream?
And your buffer[2] is leaking - better allocate 2-byte array locally like
char buffer[2],
, accessing it like buffer[0] and buffer[1], and there will be no need to delete it.
And you should not delete file_name in your class, as you do not allocate it, but only copy pointer value. You should not
Expand|Select|Wrap|Line Numbers
  1. char * c = "abcde";
  2. delete c;
Sep 25 '08 #12
Airslash
221 100+
added following code in my read method:

Expand|Select|Wrap|Line Numbers
  1. cout << "lowbyte: " << lowbyte << endl;
  2.     cout << "highbyte: " << highbyte << endl;
  3.  
result:

lowbyte: 65480
highbyte: 36
Amount of files in C:\Netss\Florensia\Data\Map.pak : 65480
Sep 25 '08 #13
donbock
2,426 Expert 2GB
result:
lowbyte: 65480
highbyte: 36
Amount of files in C:\Netss\Florensia\Data\Map.pak : 65480
lowbyte: 65480 = 0xFFC8
highbyte: 36 = 0x24
Looks like there's been sign-extension in lowbyte. Declaring buffer as an array of unsigned char should fix that (or you could mask the lowbyte and highbyte values with 0xFF). Even if we manually remove the sign-extension, the resulting combined value of 0x24C8 (9416) is not what you expect. Maybe you should dump the first several bytes of the file and compare that to what's in your buffer array. Maybe the file format is not what you expect.
Sep 25 '08 #14
Airslash
221 100+
the file format matches, I have the technical details right next to me.
got them not so long ago:

- 2 bytes reversed : amount of files
- 2 zero padding bytes
---- repeating area ----
- 196 bytes : filename
- 2 zero padding bytes
- 2 bytes : start location
- 2 zero padding bytes
- 2 bytes : file length
---- end of area ----
- file contents

I even opened the files with Ultraedit in Binary view so I can see the raw output in hex values

I'll see about declaring the buffer, what it gives, stay tuned :)
Sep 25 '08 #15
Airslash
221 100+
Problem solved......


the issue was a typo in the patch, so nothing got loaded and it was just reading random stuff from memory.
Sep 25 '08 #16

Sign in to post your reply or Sign up for a free account.

Similar topics

24
by: Norm | last post by:
Could someone explain for me what is happening here? char *string; string = new char; string = "This is the string"; cout << string << std::endl; The output contains (This the string) even...
30
by: Tim Johansson | last post by:
I'm new to C++, and tried to start making a script that will shuffle an array. Can someone please tell me what's wrong? #include <iostream.h> #include <string.h> int main () {...
12
by: Vaca Louca | last post by:
Hello, I write an ISAPI authentication module which uses Berkeley DB and want it to be as efficient as possible. Both ISAPI and BerkeleyDB use arrays of chars (char *) to pass and receive...
3
by: Vishal Ladha | last post by:
Hi ! I have been experimenting with char * for a while now. I have two pieces of code : Code1 : ===== char *ptr = "hello";
13
by: Vijay Kumar R. Zanvar | last post by:
Hello, I have few questions. They are: 1. Is "const char * const *p;" a valid construct? 2. How do I align a given structure, say, at 32-byte boundary? 3. Then, how do I assert that a given...
14
by: mr_semantics | last post by:
I have been reading about the practise of casting values to unsigned char while using the <ctype.h> functions. For example, c = toupper ((unsigned char) c); Now I understand that the standard...
74
by: aruna.mysore | last post by:
Hi all, I have a simple definitioin in a C file something like this. main() { char a; ....... int k; }
6
by: DaTurk | last post by:
Hi, I have several interfaces in CLI that I access via c#. My problem is, is that down in the unmanaged c++, which the CLI lies on top of, I have a lot of c_str() happening. But all of my...
19
by: Dancefire | last post by:
Hi, everyone It might be a simple question, but I really don't know the answer. char c = '1'; cout << c; The above code will only output a '1' rather than 0x31; If I use int cast, it can...
21
by: Fastro | last post by:
int myfun(char *sourcebuf) { char *destbuf; char ch; while (*sourcebuf != '\0') { *destbuf++=*sourcebuf++; --crashed here }; return 1; }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.