SCV
DPP Game Researcher
- 178
- Posts
- 17
- Years
- Los Angeles
- Seen Jan 9, 2015
Mystery Gift Shiny Prevention in D/P/P with video (check fist post)
Here is a link to the video I made I will write an explanation of what is going on and post it as soon as I finish. https://rapidshare.com/files/173485208/MG.avi
I also made a video for Manaphy being able to hatch shiny. https://rapidshare.com/files/173635424/Manaphy.avi
-----------------------------------------------------------------------
Hi everyone. Just thought you might all want to know about an interesting piece of code that I found in the DS pokemon games.
There was a rumor that Mystery Gift pokemon could not be shiny. This was said by some people on smogon.
I finally got the time to study the Mystery gift pokemon generation routine.
After the PID is calculated, there is a shiny check. If the pokemon is shiny it calculates another PID and then checks again. It keeps doing this untill its not shiny.
This does not come into effect for pokemon like WCS milotic who are set to always be shiny.
But as long as it has variable nature/gender/ability it cannot be shiny.
Think of this as Nintendo's way of making shiny events more special.
What this means is that any shiny mystery gift event pokemon that someone is offering is a hack (except WCS Milotic). It doesn't matter who checked it. A hack checker is only as good as how much knowledge he/she has. Since this is a new discovery most hack checkers don't have this knowledge.
EDIT: Another interesting note is that they tried to prevent shiny manaphys was well. But I found a bug in the code that makes them possible if you trade the egg you received from the green man and the trainer you traded it to has a "proper" ID and Secret ID.
_______________________________________________________________
The video is uploaded here are some notes:
The following are used.
ID = 06218 = 0x184A
SID= 31630 = 0x7B8E
Use a hex/decimal converter to get the numbers on the right. We do this because data it is more convenient to study data in hex notation than in decimal notation.
Now the first thing I do is set up a breakpoint for the value that I figured out is the multiplier value for the special RNG (Random Number Generator) used in the generation of mystery gift pokemon.
What will happen is that when the game gets to that line of code (during the generation of the Deoxys) it will pause the game and let me look at the current data.
What happens is that the game pulls two half words (word == 4 Bytes) from two specific locations; 0x21D37B4 and 0x4000100.
It takes those two and makes a word, stored in r0.
Line 0x201BA12 reads mul r1, r0
This means that the values in r1 and r0 get multiplied. The result is store in r1.
The next line is add r0, r1, 1.
This means add 1 to r1 and store the result in r0.
This will be the the PID of the pokemon pending a successful non-shiny check.
Shortly after the game returns to 0x2042FB8, then shortly after it comes to line 0x2042FC8 : bl 2068AACh
This is the call to the (non-)shiny check function. This function check whether the pokemon fails to be shiny. (this is 29 seconds into the video)
Now when the game reaches the shiny check. The values in r0 and r1 are the "Full ID", that is a word such that the first half word (from left to right) is the ID and the second is the Secret ID, and the PID, respectively.
Now, the way shinyness is determing is that the PID is split up into two half words, we will call on HID and the other LID, the following opetation is computed:
HID xor LID xor SID xor ID
You use the associative law (which hold for this operation to compute)
Then if the result is strictly less that 8 (0 to 7) the pokemon is shiny. Otherwise it is not shiny. This is where the 8/65535 = 1/8192 shiny probability comes from.
The actual computation of xot operation is done in lines 0x2068ABC, 0x2068AC0, and 0x2068AC2. Then in line 0x2068AC4, the result is compare to 8.
In line 0x2068AC6, the game checks whether the results of the comparison was that the value calculated was greater than or equal to 8 (i.e., checks whether it is not shiny)
If it turns out to be true the function returns 0.
When it gets back to 0x2043FCC it compares the value returned to 0.
It it is 0 then the game skips the section of code from 0x2042FD0 to 0x2042FE6 and continues with the pokemon generation.
I did a second run of the Deoxys to tamper with the results for demostration purposes. What I do is change the values of the result of
HID xor LID xor SID xor ID so that the game will think it was less than 8. Then show what happens.
When this happens the game goes to line 0x2068AC8 rather than 0x2068ACC and stores 1 in r0 rather than 0 in r0.
This causes 0x2042FCE to display false and this time the =section of code from 0x2042FD0 to 0x2042FE6 is not skipped. Once again 0x201BA10 is called (to calculate the PID), this time from line 0x2042FD2 and then 0x2068AAC (to check shinyness) from line 0x2042FDC.
I then make it fail 2 more times to demostrate that it will loop and get another PID, then check again, then get another PID then check again, etc until the result of HID xor LID xor SID xor ID is greater or equal to 8.
I included the manaphy egg case to show that it does not go through the same check at time of receipt.
Feel free to ask any questions.
Here is a link to the video I made I will write an explanation of what is going on and post it as soon as I finish. https://rapidshare.com/files/173485208/MG.avi
I also made a video for Manaphy being able to hatch shiny. https://rapidshare.com/files/173635424/Manaphy.avi
-----------------------------------------------------------------------
Hi everyone. Just thought you might all want to know about an interesting piece of code that I found in the DS pokemon games.
There was a rumor that Mystery Gift pokemon could not be shiny. This was said by some people on smogon.
I finally got the time to study the Mystery gift pokemon generation routine.
After the PID is calculated, there is a shiny check. If the pokemon is shiny it calculates another PID and then checks again. It keeps doing this untill its not shiny.
This does not come into effect for pokemon like WCS milotic who are set to always be shiny.
But as long as it has variable nature/gender/ability it cannot be shiny.
Think of this as Nintendo's way of making shiny events more special.
What this means is that any shiny mystery gift event pokemon that someone is offering is a hack (except WCS Milotic). It doesn't matter who checked it. A hack checker is only as good as how much knowledge he/she has. Since this is a new discovery most hack checkers don't have this knowledge.
EDIT: Another interesting note is that they tried to prevent shiny manaphys was well. But I found a bug in the code that makes them possible if you trade the egg you received from the green man and the trainer you traded it to has a "proper" ID and Secret ID.
_______________________________________________________________
The video is uploaded here are some notes:
The following are used.
ID = 06218 = 0x184A
SID= 31630 = 0x7B8E
Use a hex/decimal converter to get the numbers on the right. We do this because data it is more convenient to study data in hex notation than in decimal notation.
Now the first thing I do is set up a breakpoint for the value that I figured out is the multiplier value for the special RNG (Random Number Generator) used in the generation of mystery gift pokemon.
What will happen is that when the game gets to that line of code (during the generation of the Deoxys) it will pause the game and let me look at the current data.
What happens is that the game pulls two half words (word == 4 Bytes) from two specific locations; 0x21D37B4 and 0x4000100.
It takes those two and makes a word, stored in r0.
Line 0x201BA12 reads mul r1, r0
This means that the values in r1 and r0 get multiplied. The result is store in r1.
The next line is add r0, r1, 1.
This means add 1 to r1 and store the result in r0.
This will be the the PID of the pokemon pending a successful non-shiny check.
Shortly after the game returns to 0x2042FB8, then shortly after it comes to line 0x2042FC8 : bl 2068AACh
This is the call to the (non-)shiny check function. This function check whether the pokemon fails to be shiny. (this is 29 seconds into the video)
Now when the game reaches the shiny check. The values in r0 and r1 are the "Full ID", that is a word such that the first half word (from left to right) is the ID and the second is the Secret ID, and the PID, respectively.
Now, the way shinyness is determing is that the PID is split up into two half words, we will call on HID and the other LID, the following opetation is computed:
HID xor LID xor SID xor ID
You use the associative law (which hold for this operation to compute)
Then if the result is strictly less that 8 (0 to 7) the pokemon is shiny. Otherwise it is not shiny. This is where the 8/65535 = 1/8192 shiny probability comes from.
The actual computation of xot operation is done in lines 0x2068ABC, 0x2068AC0, and 0x2068AC2. Then in line 0x2068AC4, the result is compare to 8.
In line 0x2068AC6, the game checks whether the results of the comparison was that the value calculated was greater than or equal to 8 (i.e., checks whether it is not shiny)
If it turns out to be true the function returns 0.
When it gets back to 0x2043FCC it compares the value returned to 0.
It it is 0 then the game skips the section of code from 0x2042FD0 to 0x2042FE6 and continues with the pokemon generation.
I did a second run of the Deoxys to tamper with the results for demostration purposes. What I do is change the values of the result of
HID xor LID xor SID xor ID so that the game will think it was less than 8. Then show what happens.
When this happens the game goes to line 0x2068AC8 rather than 0x2068ACC and stores 1 in r0 rather than 0 in r0.
This causes 0x2042FCE to display false and this time the =section of code from 0x2042FD0 to 0x2042FE6 is not skipped. Once again 0x201BA10 is called (to calculate the PID), this time from line 0x2042FD2 and then 0x2068AAC (to check shinyness) from line 0x2042FDC.
I then make it fail 2 more times to demostrate that it will loop and get another PID, then check again, then get another PID then check again, etc until the result of HID xor LID xor SID xor ID is greater or equal to 8.
I included the manaphy egg case to show that it does not go through the same check at time of receipt.
Feel free to ask any questions.
Last edited: