Jump to content

PHP & IV's


Recommended Posts

I vaguely understand the bit shifting required to set IV's.

Here's the C# code I use for, say, setting ATTIV:

uint i = rawdata.GetUInt(0x38);
i &= 0xFFFFFC1F;
uint val = (uint)(value << 5);
i |= val;
rawdata.SetUInt(0x38, i);

However, when I port the code to PHP, it gets mangled on most of them. Apparently, PHP's typing is rather awkward and numbers default to a signed integer, and all math is signed integers for the most part.

Currently, I'm attempting to use GMP as seen below:

$newIV = $row['AttIV'];
$i = substr($q,0x38,8);
$i = gmp_and($i , 0xFFFFFC1F);
$val = gmp_mul($newIV,gmp_pow(2,5));
$i = gmp_or($i, $val);
$i = pack("V", $i);
$q = substr($q,0,0x38).$i.substr($q,0x3C);

For reference, $q is the loaded pokemon.

Link to comment
Share on other sites

$newIV = $row['AttIV'];
$i = unpack("V", substr($q,0x38,4));
$i &= 0xFFFFFC1F; // Clear Attack IV
$i |= ($newIV & 0x1F) << 5; // Set new attack IV
$q = substr($q,0,0x38).pack("V",$i).substr($q,0x3C);

You only need GMP for 64 bit arithetic on 32 bit systems, for instance the PRNG (but you can use bcmath for that, although it's slow)

Link to comment
Share on other sites

$newIV = $row['AttIV'];
$i = unpack("V", substr($q,0x38,4));
$i &= 0xFFFFFC1F; // Clear Attack IV
$i |= ($newIV & 0x1F) << 5; // Set new attack IV
$q = substr($q,0,0x38).pack("V",$i).substr($q,0x3C);

You only need GMP for 64 bit arithetic on 32 bit systems, for instance the PRNG (but you can use bcmath for that, although it's slow)

I still have the same problem, only SPDEF gets set, and HP is set at 1? Odd.

http://pastebin.com/wuk0471x

Here is a resulting file with the GTS portion snipped out, you can load it in pokesav to see. For reference, I'm *not* running a 64-bit OS.

http://dl.dropbox.com/u/17115146/result.bin

Link to comment
Share on other sites

There are two problems, lack of list(,) when unpacking and 32 bit overflow if the pokemon is nicknamed. You could temporarly unset the nickname flag by temporarly masking byte 0x3B with 0x7F and using your code, or proceed by 16-bit words, for instance for the HP IV use:

$newIV = $row['HPIV'];
list(,$i) = unpack("v", substr($q,0x38,2)); // HP, Attack, Def
$i &= 0xFFE0; // Clear HP IV
$i |= ($newIV & 0x1F) << 0; // Set new HP IV
$q = substr($q,0,0x38).pack("v",$i).substr($q,0x3A);

Of course for speed you'll need 0x39-0x3A, and for SA/SDef 0x3A-0x3B... for the other solution:

$n = ord($q[0x3B]);
$nicknamed = $n>>7;
$q[0x3B] = chr($n & 0x7F);
// ... Your pastebin code fixed with list(,) before unpacks
if($nicknamed) $q[0x3B]=chr(ord($q[0x3B]) | 0x80);

Third and best solution is use a 64 bit OS.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...