0

i need to read a binary file that contains this structure:

struct iqmheader
{
    char magic[16]; // the string "INTERQUAKEMODEL\0", 0 terminated
    uint version; // must be version 2
    uint filesize;
    uint flags;
    uint num_text, ofs_text;
    uint num_meshes, ofs_meshes;
    uint num_vertexarrays, num_vertexes, ofs_vertexarrays;
    uint num_triangles, ofs_triangles, ofs_adjacency;
    uint num_joints, ofs_joints;
    uint num_poses, ofs_poses;
    uint num_anims, ofs_anims;
    uint num_frames, num_framechannels, ofs_frames, ofs_bounds;
    uint num_comment, ofs_comment;
    uint num_extensions, ofs_extensions; 
};

Is there an elegant way of doing this? I tried the javolution lib in that way:

import javolution.io.Struct;
import java.nio.ByteOrder;

public class IqmHeader extends Struct {
    public final UTF8String magic = new UTF8String(16);
    public final Unsigned8 version = new Unsigned8();
    public final Unsigned8 filesize = new Unsigned8();   
}

The first 2 values (magic and version) are correct but for the third one i´m already getting 0 which is wrong.

File opened with Hex Editor (first bytes, not whole file):

Here is the output from the hex editor:

49 4E 54 45 52 51 55 41 4B 45 4D 4F 44 45 4C 00 02 00 00 00 10 EF 03 00 00 00 00 00 60 03 00 00 7C 00 00 00 02 00 00 00 DC 03 00 00 06 00 00 00 45 07 00 00 0C 04 00 00 AC 0B 00 00 A0 9B 01 00 B0 27 02 00 4B 00 00 00 C0 B3 02 00 4B 00 00 00 D0 C1 02 00 01 00 00 00 98 DB 02 00 65 00 00 00 4D 01 00 00 AC DB 02 00 70 E2 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 6F 64

I must admit I dont really know how to read this. The first 16 Bytes is the string followed by "00". Then the Version "02" - here i dont know how many bytes the uint takes

Any suggestions?

Alex Tbk
  • 2,042
  • 2
  • 20
  • 38
  • Can you open the file in a hex editor and ensure that the filesize is set to a non-zero value in the file? – nanofarad Jul 30 '13 at 21:44
  • Alex: Please edit your original post with it. – nanofarad Jul 30 '13 at 21:56
  • 1
    Not familiar with Javolution, but are you sure that Unsigned8 is the right type to use in your definition? I'm guessing that a C int would correspond to Unsigned32 (assuming such a class exists in Javolution). – Trevor Freeman Jul 30 '13 at 22:37

2 Answers2

0

Use DataInputStream and readUnsignedByte, readUnsignedShort, readUTF etc to create the structure.

You can use a Java class to represent the structure:

public class IQMHeader {
    String magic; // the string "INTERQUAKEMODEL\0", 0 terminated
    long version; // must be version 2
    long filesize;
    long flags;
    long num_text, ofs_text;
    long num_meshes, ofs_meshes;
    long num_vertexarrays, num_vertexes, ofs_vertexarrays;
    long num_triangles, ofs_triangles, ofs_adjacency;
    long num_joints, ofs_joints;
    long num_poses, ofs_poses;
    long num_anims, ofs_anims;
    long num_frames, num_framechannels, ofs_frames, ofs_bounds;
    long num_comment, ofs_comment;
    long num_extensions, ofs_extensions; 
};

You can read an unsigned int like so:

long unsigned = input.readInt() & 0xffffffffL;
David Xu
  • 5,555
  • 3
  • 28
  • 50
  • Hmm that doesnt seem to work: fis = new FileInputStream("c:\\temp\\mrfixit.iqm"); DataInputStream dis = new DataInputStream(fis); System.out.println(dis.readUTF()); --> java.io.UTFDataFormatException: malformed input around byte 21 – Alex Tbk Jul 30 '13 at 22:10
  • 2
    I forgot to tell, that data is stored little endian. I think DataInputStream is big endian – Alex Tbk Jul 30 '13 at 22:15
0

As commented, you may want to try using Unsigned32 to represent the version and other C ints in your Java class instead of Unsigned8, since a C int should be 4 bytes and an Unsigned8 only represents 1 byte.

Trevor Freeman
  • 7,112
  • 2
  • 21
  • 40