willaien Posted March 19, 2011 Posted March 19, 2011 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.
xfr Posted March 19, 2011 Posted March 19, 2011 $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)
willaien Posted March 19, 2011 Author Posted March 19, 2011 $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
xfr Posted March 19, 2011 Posted March 19, 2011 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.
willaien Posted March 20, 2011 Author Posted March 20, 2011 Thanks for your help. I implemented the option of temporarily storing the nickname bit.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now