problem reading data in binary mode

closed account (236Rko23)
hi everyone, i have this problem: i'm makeing a program to list/add/extract files from a archive(it's a .DRV file from a psx game, which has all the actual files used by the game)
The problem is that when i read a byte with value bigger than 127, it gives me some weird error: for 127 it returns 127(0x7F), but for 128(0x80) it returns 16777088 (0xFFFF80), tried using a unsigned short int but returns 0xFF80

this is a piece of the archive (the file table)
00000000 80 00 00 00 01 00 00 00 00 00 00 00 22 2B 43 3A 45 56 45 4E 54 00 00 00 00 00 00 00 00 00 00 00 ............"+C:EVENT...........
00000020 80 00 00 00 11 00 00 00 00 00 00 00 D2 22 43 3A 4F 42 4A 45 43 54 00 00 00 00 00 00 00 00 00 00 ............."C:OBJECT..........
00000040 80 00 00 00 BD 01 00 00 00 00 00 00 2C AD 5E 3A 45 56 4F 5F 50 41 4B 00 00 00 00 00 00 00 00 00 ............,.^:EVO_PAK.........
00000060 80 00 00 00 C8 01 00 00 00 00 00 00 14 64 62 3A 44 45 42 55 47 00 00 00 00 00 00 00 00 00 00 00 .............db:DEBUG...........
00000080 01 41 52 43 52 0C 00 00 1C 12 00 00 D8 DF EE 39 55 4E 49 54 5F 45 46 46 00 00 00 00 00 00 00 00 .ARCR..........9UNIT_EFF........
000000A0 01 50 41 4B 55 0C 00 00 FC C4 06 00 22 C2 EF 3A 41 52 45 41 30 34 00 00 00 00 00 00 00 00 00 00 .PAKU......."..:AREA04..........
000000C0 01 50 41 4B 2E 0D 00 00 80 E9 06 00 22 C2 EF 3A 41 52 45 41 30 35 00 00 00 00 00 00 00 00 00 00 .PAK........"..:AREA05..........
000000E0 01 50 41 4B 0C 0E 00 00 00 F8 06 00 22 C2 EF 3A 41 52 45 41 30 31 00 00 00 00 00 00 00 00 00 00 .PAK........"..:AREA01..........
00000100 01 50 41 4B EB 0E 00 00 EC 42 06 00 22 C2 EF 3A 41 52 45 41 30 36 00 00 00 00 00 00 00 00 00 00 .PAK.....B.."..:AREA06..........
00000120 01 50 41 4B B4 0F 00 00 8C 54 07 00 22 C2 EF 3A 41 52 45 41 30 32 00 00 00 00 00 00 00 00 00 00 .PAK.....T.."..:AREA02..........
00000140 01 50 41 4B 9F 10 00 00 50 72 07 00 22 C2 EF 3A 41 52 45 41 30 33 00 00 00 00 00 00 00 00 00 00 .PAK....Pr.."..:AREA03..........
00000160 01 50 41 4B 8E 11 00 00 78 E3 06 00 22 C2 EF 3A 41 52 45 41 30 30 00 00 00 00 00 00 00 00 00 00 .PAK....x..."..:AREA00..........
00000180 01 50 41 4B 6B 12 00 00 40 FF 06 00 22 C2 EF 3A 41 52 45 41 30 38 00 00 00 00 00 00 00 00 00 00 .PAKk...@..."..:AREA08..........
000001A0 01 50 41 4B 4B 13 00 00 60 A3 06 00 22 C2 EF 3A 41 52 45 41 30 39 00 00 00 00 00 00 00 00 00 00 .PAKK...`..."..:AREA09..........
000001C0 01 50 41 4B 20 14 00 00 A4 1E 07 00 22 C2 EF 3A 41 52 45 41 31 30 00 00 00 00 00 00 00 00 00 00 .PAK ......."..:AREA10..........
000001E0 01 50 41 4B 04 15 00 00 74 B2 07 00 24 C2 EF 3A 41 52 45 41 31 31 00 00 00 00 00 00 00 00 00 00 .PAK....t...$..:AREA11..........
00000200 01 50 41 4B FB 15 00 00 34 DC 06 00 22 C2 EF 3A 41 52 45 41 30 37 00 00 00 00 00 00 00 00 00 00 .PAK....4..."..:AREA07..........
00000220 01 53 43 43 D7 16 00 00 F0 00 00 00 2E C2 EF 3A 56 53 53 56 45 52 00 00 00 00 00 00 00 00 00 00 .SCC...........:VSSVER..........
00000240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
000002A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
000002C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
000002E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................


as i figure it it reads every 32 bytes like this:
* first 4 bytes: 1 byte the Type and 3 bytes the Extension if not a folder
* second 4 bytes are the address, it's in big endian, and the real address is the numeber multiplyed by 2048 (0x800) (ej. 01 BD x 800 = DE800 = 911360)
* third 4 bytes: the size of the file
* fourth 4: no idea (attributes?)
* fifth and sixth: the name
* seventh and eigth: no idea


well, here's the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <fstream>
using namespace std;
typedef unsigned short int uint;
int length(0);

void GetData (char Input[32],int * Address, int * Size){  //HERE IS THE PROBLEM
   //look at the end of the post, the output of this
    cout << hex << short (unsigned (int (Input[4]))) << " " << unsigned (short (int (Input[5]))) << " " << unsigned (short (int (Input[6]))) << " " << unsigned (short (int (Input[7]))) \
    << "\t" << unsigned (short (int (Input[8]))) << " " << unsigned (short (int (Input[9]))) << " " << unsigned (short (int (Input[10]))) << " " << unsigned (short (int (Input[11]))) << endl;

    int a = (unsigned (short (int (Input[4]))) +  unsigned (short (int (Input[5]))) * 256 +  unsigned (short (int (Input[6]))) * 65536 +  unsigned (short (int (Input[7]))) * 16777216)*2048;
    int b = (unsigned (short (int (Input[8]))) +  unsigned (short (int (Input[9]))) * 256 +  unsigned (short (int (Input[10]))) * 65536 +  unsigned (short (int (Input[11]))) * 16777216);
    cout << dec << a << "\t\t" << b << endl;



return;
}


void GetLength (ifstream * inFile, int * Target){
    int i = inFile->tellg();
    inFile->seekg (0, ios::end);
    *Target = inFile->tellg();
    inFile->seekg (i);
 }
bool IsDivisible (int a, int b){
    if (!a ==0 && a % b == 0){return true;}else{return false;}
}
void ListFiles (ifstream * inFile){
    char buffer [32];
    int Address = 0;
    int Size = 0;

    inFile->seekg(0);

    for (int i = 0; i < 60; i++){
    inFile->read(buffer, 32);
    GetData(buffer, &Address, &Size);

    }

    return;

}


int main(int argc, char *argv[]) {



    ifstream drvfile(argv[1], ios::binary);
    if (drvfile.is_open()){


    GetLength (&drvfile, &length);
    cout << length << "bytes" << endl;


    ListFiles(&drvfile);  //just testing the function


    drvfile.close();
    }
    else {cout << "error al abrir el archivo:" << argv[1] << endl;}

    return 0;
}


and this is th output:
11976704bytes
1 0 0 0 0 0 0 0
2048 0
11 0 0 0 0 0 0 0
34816 0
ffbd 1 0 0 0 0 0 0
387072 0
ffc8 1 0 0 0 0 0 0
409600 0
52 c 0 0 1c 12 0 0
6459392 4636


FFBD are 2 bytes and the value is suposely a short int (1 byte)
and 387072 is BD*800, the correct value should be 911360 which is 1BD*800

C52 on the other side is correct 6459392 which is C52*800



anyone has any idea? what i need is to get the unsigned value for every byte (0-255) so that I can sum and multiply them to get the address value.
It seems to me that the file is opened as text, bypassing the binary flag


NOTE: Using linux (ubuntu 9.10) and Code:blocks with gcc
Last edited on
it gives me some weird error: for 127 it returns 127(0x7F), but for 128(0x80) it returns 16777088 (0xFFFF80), tried using a unsigned short int but returns 0xFF80

that's because your input is char rater than unsigned char
a short int (1 byte)
? char is one byte, short is two bytes
(unsigned (short (int (Input[4])))
this could be your problem. this does not convert something to unsigned short int. it first converts input to (signed) int, then to (signed) short and then to unsigned (again int).
you don't really need this part at all. int is enough to make it print a number and not a char
Shouldn't you allocate some memory?

1
2
3
4
5
void ListFiles (ifstream * inFile){
    uint *buffer [32];
    ...
    inFile->read(*buffer, 32);


Or use static array?

I read the declaration of read method of ifstream and it requires array of char;

istream& read ( char* s, streamsize n );


http://www.cplusplus.com/reference/iostream/istream/read/
closed account (236Rko23)
sorry copied the code without cheking, i made the change ahd forgot to un do it before coping it here :P
fixed the first post

now, about the unsigned char, the problem is that istream.read need a char*. if i declare buffer as uchar the compiler gives me an error about invalid conversion from uchar to char.

i've read something about using memcpy to copy from char to uchar iwthout doing conversion, i'll give it a try. If it works i'll post the solution here

closed account (236Rko23)
Done! ^^
memcpy worked flawlessly from the first try ^_^

The solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef unsigned char uchar;

void GetData (char Input[32],int * Address, int * Size){
    uchar Input2 [32];    //second char array but unsigned

    memcpy (Input2,Input,32);  //copy from Input to Input2 without doing any convesion

    int a = (int (Input2[4]) +  int (Input2[5]) * 256 +  int (Input2[6]) * 65536 +  int (Input2[7]) * 16777216)*2048;
    int b = (int (Input2[8]) +  int (Input2[9]) * 256 +  int (Input2[10]) * 65536 +  int (Input2[11]) * 16777216);
    cout <<  a << "\t\t" << b << endl;

 return;
}


This time all the results were correct so it worked. Thank you very much for the great help :P
problem is that istream.read need a char*.


you can cast the pointer to unsigned characters of array to pointer to signed characters of array:

1
2
3
                unsigned char array[10];

	is.read((char *)array, 10);


So you shouldn't make an another array.
closed account (236Rko23)
oh, i'll try that. But i ended up needing a unsigned char to calculate the file address. if i use a signed char the calculation gives me a incorrect number.

this is the finished function. The one above was just for testing concepts.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void GetData (char Input[32],uint * Address, uint * Size,char * Name, char * Type, char * Extension){

    uchar Input2 [32];           // this is to fix the calculation from using number with negative value after 127 0x7F
    memcpy (Input2,Input,32);    // because of the signed chars


    *Address = (Input2[4] + Input2[5] * 256 + Input2[6]  * 65536 + Input2[7]  * 16777216) * 2048;   // This is the adrress (bytes 5-8) from base16 to base10 by 2048 (0x800)
    *Size    = (Input2[8] + Input2[9] * 256 + Input2[10] * 65536 + Input2[11] * 16777216);          // This is the size (bytes 9-12) from base16 to base10

    for (int i = 16; i <= 23; i++){              // The name is 8 bytes long and is from byte 17 to 24
    Name[i-16] = Input[i];}

    for (int i = 1; i <= 3; i++){                // The Extension is 3 bytes long and is from byte 2 to 4
    Extension[i-1] = Input[i];}

    switch (Input2[0]){                    // the first byte is the type of the address content
        case 1:      *Type = 1;break;           // 0x01 for file
        case 128:    *Type = 2;break;           // 0x80 for folder
        default:     *Type = 0;break;           // defaults to unknown
    }
return;
}


any recomendation?
Topic archived. No new replies allowed.