Author Topic: Oddity???  (Read 4474 times)

-gone away-

  • *
  • Posts: 385
    • View Profile
Oddity???
« on: 2006-01-10 02:58:11 »
Code: [Select]
String ^FileEditor::BinaryToNumber(array<Byte> ^data)
{
String ^strTmp;
double dblTmp;
for (double i=0 ; i < data->GetLength(0) ; i++ )
{
if (i == 0)
{ dblTmp = dblTmp + data[i]; }
else
{ dblTmp = dblTmp + (data[i] * (pow(256,i)));}
}
return strTmp = dblTmp.ToString();
}


Okay thats my current conversion code to convert from a byte array to a number. It works pretty well, squished it up a bit to take up less space in post.

However i encounter something very odd in one file in particular which hopefully someone will be able to give me an explanation for.
In file scene247, on the leg of emerald weapon, the stats for gil and exp come out at 4294967295 which is == to 256^4(power of) -1, in other words it comes out the max possible number that can go in this place. e.g.

Ap: 65535 - max number for bytes
Exp: 4294967295 - max number for bytes
Gil: 4294967295 - max number for bytes

Now whats got me weirded out is that if you open the same file with scenester or sceneedit you get the follow stats and i dont know why.

Ap: 65535
Exp: -1
Gil: -1

Are my values wrong or are they'rs? Im pretty sure mine are right, but i thought it best to check in case they are not. keep in mind that you never recieve these rewards in game because they are only on the leg.

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Oddity???
« Reply #1 on: 2006-01-10 04:01:54 »
4294967295 == -1 == 0xFFFFFFFF

Check signed/unsigned dwords.


L. Spiro

-gone away-

  • *
  • Posts: 385
    • View Profile
Oddity???
« Reply #2 on: 2006-01-10 07:19:08 »
I suppose its really just a matter of preference as to how i display it then.

mirex

  • *
  • Posts: 1645
    • View Profile
    • http://mirex.mypage.sk
Oddity???
« Reply #3 on: 2006-01-10 11:37:44 »
Some code speedup:
- no need to call pow(), simple multiplying can be faster
- don't call data->GetLength() multiple times (in every cycle loop), when it can be called only once .. you can see speedup especially in case of larger arrays of data
- why using floating point number 'double' when the result is an integer ? also using floating point for a loop counter and indexer is a nonsense.
- reason why you see 4294967295 instead of -1 is that you are multiplying  0xFF * 256 in every loop instead of treating it as -1

Code: [Select]

String ^FileEditor::BinaryToNumber(array<Byte> ^data)
{
   String ^strTmp;
   integer dblTmp;
   integer i, c;

   c = data->GetLength(0);
   dblTmp = 0;

   for (i=0 ; i <c; i++ )
   {
      dblTmp = dblTmp * 256;
      dblTmp = dblTmp + data[i];
   }

   // here you should check if the number is negative (depending on its bits)

   strTmp = dblTmp.ToString();
   return strTmp;
}


but in fact, fastest and best way is to copy/read the data into the proper data type.

Code: [Select]

this code is in C++ syntax because I don't understand the language you're using properly

String* FileEditor::BinaryToNumber( BYTE *data)
{
   long int  *li;   // this should be pointer to the 32bit integer number, which can contain numbers from -2 147 483 648 to 2 147 483 647
   String strTmp;

   li = (long int*)data;

   strTmp = li->ToString();
   return strTmp;
}

but this process can be done in many ways, depends on your implementation. Consult your help about this, you should find some advice there.

-gone away-

  • *
  • Posts: 385
    • View Profile
Oddity???
« Reply #4 on: 2006-01-11 02:12:10 »
Quote
- no need to call pow(), simple multiplying can be faster


The reason for pow is that some take up four bytes, 256 * 256 * 256 * 256. just multiplying will only go up to 2 bytes ... wont it?.

Quote
- don't call data->GetLength() multiple times (in every cycle loop), when it can be called only once .. you can see speedup especially in case of larger arrays of data


Never considered that.. .thanks for the heads up. Speed is not really something i consider in such a small app.

Code: [Select]
- why using floating point number 'double' when the result is an integer ? also using floating point for a loop counter and indexer is a nonsense.

Not anymore it isn't, you now have to be either a double or a float. If either of them aren't it doesn't compile. I assume they changed it because ints wouldn't return the correct result above a certain point. I used double instead of float because float returns 4.294967E+09 which is less understandable to  me... also it was about 4:30AM when i went to post that. lol. (EDIT- no it wasn't i was thinking of my prevous post, it would've been about miday  :o )

Quote
this code is in C++ syntax because I don't understand the language you're using properly


Its just Visual C++ 2005 - windows form app, Replace '*' with '^' basically. From the MSDN: ^ Declares a handle to an object on the managed heap.

Thanks for your help, i should be able to make a better method based off your second example. Its given me a few idea's.

L. Spiro

  • *
  • Posts: 797
    • View Profile
    • http://www.memoryhacking.com/index.php
Oddity???
« Reply #5 on: 2006-01-11 07:46:32 »
To expound.

Quote
- no need to call pow(), simple multiplying can be faster
Quote
The reason for pow is that some take up four bytes, 256 * 256 * 256 * 256. just multiplying will only go up to 2 bytes ... wont it?.
Actually you want to do a bitwise shift.

This also fixes integer overflow problems you may have had with pow() (while using float type), which is the reason you used double in the first place, so that can be removed and replaced by a DWORD.



Quote
- reason why you see 4294967295 instead of -1 is that you are multiplying 0xFF * 256 in every loop instead of treating it as -1
smithie’s method is correct at least in this part; you should calculate the value in unsigned form using 0xFF first.
Getting -1 should be done last, through a simple cast to an int or signed dword.



Quote
I used double instead of float because float returns 4.294967E+09 which is less understandable to me
It also lost precision; a float (4 bytes) can not accurately display every number that a dword can hold.  It would also corrupt your calculations when you went into pow() with a high set of numbers; the floating-point value returned would have been truncated and your final result would be corrupt.
Doubles can handle these calculations without loss in data, but with using bitwise shifts you no longer need to use even them.

It is suggested that you change to DWORD or INT and replace pow() with shifts.


L. Spiro

-gone away-

  • *
  • Posts: 385
    • View Profile
Oddity???
« Reply #6 on: 2006-01-19 05:09:16 »
I just did a huge overhaul to all my code so that none of this ByteToNumber shits required anymore.

I now do the sensible thing and just read in the numbers as they are. (who said this wasn't a learning experience?  :wink: )
for e.g.
Code: [Select]
enemyData[x]->SetMp(m_binReader->ReadInt16());

thanks for all your help, i've learnt alot about data types that i didn't understand before. Before __int8, __int16, __int32 was just all the same to me... now i know better.