Need help with longs in file opening (SOLVED)

Started by Gregjazz, Fri 18/11/2005 07:42:33

Previous topic - Next topic

Gregjazz

I'm working on a project right now that requires to be able to read a file format. So far so good, except in one section of the file format it uses longs.

I actually can't find much about longs in the AGS help documentation.

I have the file format specs, so I know how it works, but it's a little difficult interpreting it into AGS. In the part of the file format I'm working on now, the file has several parameters supposedly stored as longs. Up until then, it's used "chars", and I know how to work those in AGS.

Please any details on how this works would be appreciated. How do you interpret a file format in AGS?

Pumaman

What type of "long" are they? If it's a 32-bit long, then that's the equivalent of an AGS "int".

Gregjazz

Well actually I'm probably getting the terminology wrong.

I have a .cpp that says the file format works like this:


fwrite("chnk",4,1,verbose);
fwrite(&Waveforms.Wave
  • .Size,      sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .VelocityLow,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .VelocityHigh,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .KeyLow,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .KeyHigh,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .loopStart,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .LoopEnd,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .Root,      sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .Samplerate,   sizeof(long), 1,    verbose);
    fwrite(&Waveforms.Wave
  • .Channel,   sizeof(long), 1,    verbose);
    [/i]

    And in hexedit the example file at that place goes like this:

    Code: ags
    
                                                                   63 68 6E 6B
    DF 00 00 00 00 00 00 00    7F 00 00 00 16 00 00 00
    6B 00 00 00 FF FF FF FF      00 00 00 00 18 00 00 00
    44 AC 00 00 00 00 00 00
    


    So "63 68 6E 6B" is the "chnk" part.

    "DF 00 00 00" is the waveform size I guess. And so forth. As you can see the data is in groups of 4 numbers. I'm not sure how to interpret this in AGS...

    I know it's a whole lot to ask, but would anyone be willing to give me some tips?

HeirOfNorton

That is a 32-bit integer, the same type as used in AGS.  Each of those four numbers output by a hex-editor is a single byte, with four bytes (32 bits) per variable. I could mention endianness as well, but from the looks of those numbers it should not be necessary. Just use File.ReadRawInt and it should read them correctly.

HoN


Gregjazz

Quote from: HeirOfNorton on Sun 20/11/2005 05:35:55
That is a 32-bit integer, the same type as used in AGS.  Each of those four numbers output by a hex-editor is a single byte, with four bytes (32 bits) per variable. I could mention endianness as well, but from the looks of those numbers it should not be necessary. Just use File.ReadRawInt and it should read them correctly.

HoN



Well it makes sense, but all it returns are -1's, using the File.ReadRawInt.

Kweepa

Post your code here.

It looks (from the hex dump) like the 'CHNK' marker is not the first thing in the file, so presumably you're searching for that, then reading the subsequent numbers into a Wave structure.
I would expect loopStart to be -1 and the others, not.
Still waiting for Purity of the Surf II

Gregjazz

Quote from: SteveMcCrea on Sun 20/11/2005 17:52:43
Post your code here.

It looks (from the hex dump) like the 'CHNK' marker is not the first thing in the file, so presumably you're searching for that, then reading the subsequent numbers into a Wave structure.
I would expect loopStart to be -1 and the others, not.

Exactly.

Here's the code:

Code: ags

File *output = File.Open("Sampleset.WusikSND", eFileRead);
if (output != null) {
  int p;
  int pa;
  while ((pa != 1) || (output.EOF == false)) {
    int temp = output.ReadRawChar();
    string buffer;
    StrFormat(buffer,"%c", temp);
    if ((StrComp(buffer,"c") == 0) && (p == 0)) {
      p += 1;
      }
    else if ((StrComp(buffer,"h") == 0) && (p == 1)) {
      p += 1;
      }
    else if ((StrComp(buffer,"n") == 0) && (p == 2)) {
      p += 1;
      }
    else if ((StrComp(buffer,"k") == 0) && (p == 3)) {
      pa = 1;
      }
    else {
      p = 0;
      }
    }
    
  p = 0;
  while (p < 5) {
     int data;
     data = output.ReadRawInt();
     Display("%d", data);
     p += 1;
     }
  output.Close();
  }


Really not the best way of doing things, but it searches for the "CHNK" and then reads the subsequent data.

Kweepa

#7
That looks like it should almost work.
The problem is most likely the || in the while statement - it should be && (the way you have it, the while loop always reads to the end of the file, and then the data reading reads -1s from "past end of the file".
There are a couple of things that I'd do differently to make sure it works as expected.
Firstly, initialize your variables. I'm pretty sure AGS initializes them to zero anyway, but it can't hurt.
Secondly, you can search for the whole 'chnk' piece at once. That way you don't accidentally miss a "find" when 'c' appears, then 'h', then 'c' 'h' 'n' 'k'. Or you could just reset the search to 1 when 'c' comes up.
Lastly, I renamed output to input :)

[EDIT] The fourByteBoundaryOk "variable" is separating the two approaches to finding 'chnk'. The first, simpler approach, assumes that 'chnk' comes on a 4 byte boundary in the file, hence the "variable" name. For safety's sake, probably better to use the second approach.

Code: ags

File *input = File.Open("Sampleset.WusikSND", eFileRead);
if (input != null)
{
Ã,  bool foundChnk = false;
Ã,  int chnkStage = 0;
Ã,  while (!foundChnk && !input.EOF)
Ã,  {
Ã,  Ã,  if (fourByteBoundaryOk)
Ã,  Ã,  {
Ã,  Ã,  Ã,  int candidate = input.ReadRawInt();
Ã, Ã,  Ã, Ã,  if (candidate == 1802397795) // 0x6b6e6863 in decimal
Ã,  Ã, Ã,  Ã, {
Ã,  Ã,  Ã, Ã,  Ã, foundChnk = true;
Ã,  Ã, Ã,  Ã, }
Ã,  Ã,  }
Ã,  Ã,  else
Ã,  Ã,  {
Ã,  Ã,  Ã,  // put the values into a string
Ã,  Ã,  Ã,  string chnk = "chnk";
Ã,  Ã,  Ã,  int candidate = input.ReadRawChar();
Ã,  Ã,  Ã,  if (candidate == StrGetCharAt(chnk, chnkStage))
Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  // note - this only works for finding strings with no repeating patterns
Ã,  Ã,  Ã,  Ã,  chnkStage++;
Ã,  Ã,  Ã,  Ã,  if (chnkStage == 4) chnkFound = true;
Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  else
Ã,  Ã,  Ã,  if (candidate == StrGetCharAt(chnk, 0))
Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  // reset
Ã,  Ã,  Ã,  Ã,  chnkStage = 1;
Ã,  Ã,  Ã,  }
Ã,  Ã,  Ã,  else
Ã,  Ã,  Ã,  {
Ã,  Ã,  Ã,  Ã,  chnkStage = 0;
Ã,  Ã,  Ã,  }
Ã,  Ã,  }
Ã,  }
Ã,  if (foundChnk)
Ã,  {
Ã,  Ã,  int size = input.ReadRawInt();
Ã,  Ã,  int velocityLow = input.ReadRawInt();
Ã,  Ã,  int velocityHigh = input.ReadRawInt();
Ã,  Ã,  // etc
Ã,  Ã,  Display("size = %d, velocityLow = %d, velocityHigh = %d", size, velocityLow, velocityHigh);
Ã,  }
Ã,  else
Ã,  {
Ã,  Ã,  Display("Didn't find chnk. Perhaps I got chnk's decimal value wrong.");
Ã,  }
Ã,  input.Close();
}
else
{
Ã,  Display("Couldn't open file. Bad user! Bad!");
}
Still waiting for Purity of the Surf II

Gregjazz

What is the "if (fourByteBoundaryOk)" part?

Gregjazz

It works brilliantly now!!

I'm going to study the code to learn from it now. :)

Thanks so much for your help.

SMF spam blocked by CleanTalk