Author Topic: Coding in C++ (help please!)  (Read 2672 times)

Topher

  • *
  • Posts: 111
    • View Profile
Coding in C++ (help please!)
« on: 2005-07-24 14:16:54 »
I'm learning C++, and as a learning project I'm trying to write an application that will read the information from an FF7 save file ("savexx.ff7") and display it on screen.

I've created the following structures:

Code: [Select]
struct FF7HEAD { // The header part of the FF7 save
    unsigned char dummy [11];
} ;

struct FF7DESC { // The save description part
    USHORT checksum;
    BYTE level;
    BYTE charOne, charTwo, charThree;
    STRING name[16];
    short charCHP;
    short charMHP;
    short charCMP;
    short charMMP;
    long gil;
    long time;
    STRING location[32];
} ;

struct FF7SLOT { // The individual save slot
    FF7DESC description;
} ;

struct FF7 { // The save file as a whole.
    FF7HEAD header;
    FF7SLOT slotOne;
} ff7file;


In my main() function, I load the save file into the memory location of ff7file (see above for it)

Code: [Select]
int main() {
    FILE *ff7save;
    char ff7name[] = "save00.ff7";
    ff7save = fopen(ff7name, "rb");
    fread(&ff7file, sizeof(ff7file), 1, ff7save);
    cout << "Header:\n";
    for(int i=0; i<11; i++) {
            cout << (int)ff7file.header.dummy[i] << " ";
    }
    [snip -- just output code here]
}


the above code doesn't load the correct values into the right spot (i think they're offset a bit but i'm too tired to check right now).

when you jumble the code around and load the FF7HEAD and FF7 object (minus the header) seperately it does work... except when you get to loading gil, where it loads the 4 bytes two bytes after the current file position.

I'm pretty much a newb at c++ (have experience with PHP and java) and this is giving me a real headache... you guys are great at this kind of stuff... can you help me please?

Do note there are a bunch of shortcuts in there (the header simply contains 'dummy[]' instead of actual variables, etc), since I suck so much at C++.

(footnote: the above code was sloppily 'renewed' back to the original loading method so if anything doesn't work i screwed it up -- or i'm just a newb)

Oh, and the output that version creates is...

Code: [Select]
Header:
113 115 39 6 0 1 0 0 0 5 99

Checksum:
1792

Character Level: 0

Character 1: Barret
Character 2: None
Character 3: Unknown

HP: 14080/11777
MP: 14592/16384

Gil Held: 135168 4

Playtime: 240070144 seconds


And I'm using Dev-C++ if you wanted to know.

Mod Edit: Do not double-post

Alhexx

  • *
  • Posts: 1894
    • View Profile
    • http://www.alhexx.com
Coding in C++ (help please!)
« Reply #1 on: 2005-07-24 14:36:43 »
I'm not 100% sure, but looking at the structures, especially FF7HEAD, it seems like you met a problem I also had a long time ago...

I'm gonna quote fice's reply here:
Quote from: ficedula
Aha ... you've hit on something called 'Data alignment'.

Basically, on modern computers, data is faster to access in certain positions. A normal CPU works in 32-bit mode (4 bytes) so data on 4-byte boundaries is quicker to access...

Example: Addresses 0, 4, 8, 12 .... are quicker to access than 1, 3, 5, ....

In fact, sometimes 8 byte boundaries are even quicker than 4 byte boundaries.

In order to make use of this fact compilers often 'pad out' data so each variable rests on a 4-byte boundary (or some other boundary...odd numbered addresses are the worst of all). This often leads to records size's being multiples of 4 or 8 ... if they should be less than that, then the compiler just adds 'padding' (wasted space) to MAKE them that big. Result: faster code. Problem: You've just discovered it!



Here's the solution (I hope):
Code: [Select]
#pragma pack(push)
#pragma pack(1)

struct FF7HEAD { // The header part of the FF7 save
    unsigned char dummy [11];
} ;

struct FF7DESC { // The save description part
    USHORT checksum;
    BYTE level;
    BYTE charOne, charTwo, charThree;
    STRING name[16];
    short charCHP;
    short charMHP;
    short charCMP;
    short charMMP;
    long gil;
    long time;
    STRING location[32];
} ;

struct FF7SLOT { // The individual save slot
    FF7DESC description;
} ;

struct FF7 { // The save file as a whole.
    FF7HEAD header;
    FF7SLOT slotOne;
} ff7file;

#pragma pack(pop)


The only difference to your code are "#pragma" commands.

Try it - I hope it solves your problem.  8)

 - Alhexx

Topher

  • *
  • Posts: 111
    • View Profile
Coding in C++ (help please!)
« Reply #2 on: 2005-07-24 14:41:04 »
You, dear sir, are my saviour!

Thank you so much for your help! (and of course thanks to fice for helping you back in the day)