kwsch / PKHeX

Pokémon Save File Editor
https://projectpokemon.org/pkhex/
Other
3.74k stars 701 forks source link

About the shiny of the Gen1 and Gen2 #3002

Closed CScorpion-h closed 4 years ago

CScorpion-h commented 4 years ago

Describe the bug The shiny pokemon from Gen1 and Gen2 to Gen7 are stars in the PkHeX.

To Reproduce I Dragged the shiny pokemon of the first and second generation to the seventh generation's save.

Expected behavior The shiny pokemon should be actually square shiny. Because I tried to send a box of shiny Pikachu to the Gen7 through the Poké Transporter, and I found that they are all square shiny.That means XOR=0. As we all know, SID in the Gen1 and Gen2 is 0.

soopercool101 commented 4 years ago

Gen 7 doesn't have a square/star shiny distinction. All shinies are star shinies in generation 7 and prior. Additionally, I believe any transferred shiny to generation 8 becomes a square shiny.

Lusamine commented 4 years ago

My understanding is that while most VC Pokemon are square shiny, star shiny isn't illegal; it simply requires you to roll a shiny again. That said, I think the issue is more about how PKHeX doesn't replicate the ratio of stars to squares when the Pokemon is transferred from VC to Gen 7-8. If you import a bunch of VC Pikachu into gen 8, they pretty much are all stars.

CScorpion-h commented 4 years ago

Gen 7 doesn't have a square/star shiny distinction. All shinies are star shinies in generation 7 and prior. Additionally, I believe any transferred shiny to generation 8 becomes a square shiny.

Gen 7 doesn't have a square/star shiny distinction. All shinies are star shinies in generation 7 and prior. Additionally, I believe any transferred shiny to generation 8 becomes a square shiny.

Oh, I know it. I mean when I drag shiny pokemon from Gen1 or Gen2 to the Gen7, xor is not 0. The pid of shiny pikachu I transmitted to Gen7 match the condition of xor=0.

CScorpion-h commented 4 years ago

My understanding is that while most VC Pokemon are square shiny, star shiny isn't illegal; it simply requires you to roll a shiny again. That said, I think the issue is more about how PKHeX doesn't replicate the ratio of stars to squares when the Pokemon is transferred from VC to Gen 7-8. If you import a bunch of VC Pikachu into gen 8, they pretty much are all stars.

You've got a point there. You can download the Poké Transporter from eshop in 3ds and test it, then export the save of Gen7. You'll find that the pid of shiny pokemon is always the case where xor=0. That means when this shiny pokemon is imported into Gen8 by Pokemon Bank, it will always be square.

Atrius97 commented 4 years ago

Because I tried to send a box of shiny Pikachu to the Gen7 through the Poké Transporter, and I found that they are all square shiny. That means XOR=0.

This isn't always true. From my understanding of Anubis's and Kurt's explanations, (some discussion of this mechanic occured in the Project Pokemon a few months ago), two separate checks occur when transferring a Shiny Pokemon via Transporter into Bank.

When any VC Pokemon is transferred to Bank, it's first assigned a random PID. If that Pokemon was Shiny in Virtual Console, and that initial random PID is not Shiny (which 4095 out of 4096 times the random PID will not initially be shiny), it is manually assigned a forced Xor=0 Square Shiny PID.

However, if the random PID it's assigned IS Shiny the first time it's assigned, then it doesn't perform the manual assignment of a Square Shiny PID.

Which means, while nearly every VC Shiny will be a "xor=0" Square Shiny via the manually assigned PID, there's a 1/4096 chance the shiny will be assigned a Shiny PID first try, (and then a second 15/16 chance that Shiny PID will be a Star Shiny PID), when transferred via Transporter into Bank.

This is probably closer to an enhancement request, it isn't exactly a bug. VC Origin "Star Shiny" Pokemon are possible to obtain legitimately, they're just extremely unlikely, (approximately 1 in 4369 VC Shinies will become a Star Shiny when moved to Bank). PKHeX honors the legality of the Pokemon, just not "the ratio of how often they occur."

This request shouldn't necessarily be for "all VC Shinies to be Square Shiny, make Star Shiny VC Pokemon illegal" (because they aren't illegal, just incredibly rare), but rather for PKHeX to "randomly assign Shiny PIDs to Shiny VC Pokemon at the correct ratio of "4368 in 4369 as Square Shiny, 1 in 4369 as Star Shiny" when imported directly into a Gen 7+ save file if converted from .pk1/.pk2".

kwsch commented 4 years ago

Transporter update (VC2) has the following logic [sub_24C77C], see also [sub_24B2F0] and [sub_24A354]:

    pidType = 0x1FFFFFFFFLL;
    if ( (pk2[0x15] & 0xF) == 10 )              // DV check against 10
    {
      v23 = pk2[0x16];
      v24 = (v23 & 0xF) == 10;
      if ( (v23 & 0xF) == 10 )
        v24 = v23 >> 4 == 10;
      if ( v24 && pk2[0x15] & 0x20 )
        pidType = 0x2FFFFFFFFLL;
    }

Ultra Moon PID Generation (pk3DS byte sequence):

  v16 = *(v2 + 1);
  if ( ~v16 | HIDWORD(v16) ^ 1 )
  {
    if ( ~v16 | HIDWORD(v16) ^ 2 )
    {
      if ( !(~v16 | HIDWORD(v16) ^ 3) )
      {
        for ( i = 0; *(v2 + 35) > i; ++i )
        {
          pid3 = getRand32();
          *(v2 + 1) = v18;
          if ( isShiny(v2[4], pid3) )
            break;
        }
      }
    }
    else
    {
      pid2 = getRand32();
      *(v2 + 1) = makeShinyIfNotShiny(v2[4], pid2);
    }
  }
  else
  {
    pid1 = getRand32();
    *(v2 + 1) = makeNotShinyIfShiny(v2[4], pid1);
  }
1: Never Shiny (forces antishiny if shiny)
2: Always Shiny (forces shiny if not shiny)
3: Random

In Transporter's case, the default state is Never Shiny; if the DVs indicate it is shiny, it will generate with a shiny PID.

Using the same byte sequence as pk3DS (01 50 85 E2 05 00 50 E1 DE FF FF CA), we can find the same PID generation routine [sub_12FF30]:

  v18 = *(v3 + 1);
  if ( ~v18 | HIDWORD(v18) ^ 1 )
  {
    if ( ~v18 | HIDWORD(v18) ^ 2 )
    {
      v19 = HIDWORD(v18) ^ 3;
      if ( !(~v18 | v19) )
      {
        for ( i = 0; *(v3 + 35) > i; ++i )
        {
          pid3 = GetRandomU32();
          *(v3 + 1) = pid3;
          if ( isShiny(v3[4], pid3) )
            break;
        }
      }
    }
    else
    {
      pid2 = GetRandomU32();
      v25 = makeShinyIfNotShiny(v3[4], pid2);
      v19 = 0;
      *(v3 + 1) = v25;
    }
  }
  else
  {
    pid1 = GetRandomU32();
    v23 = makeNotShinyIfShiny(v3[4], pid1);
    v19 = 0;
    *(v3 + 1) = v23;
  }
int __fastcall makeShinyIfNotShiny(unsigned int a1, unsigned int a2)
{
  int v2; // r2
  int result; // r0

  v2 = a1 ^ (a1 >> 16);
  if ( (a2 ^ v2 ^ (a2 >> 16)) >= 0x10 )
    result = a2 | ((a1 ^ (a1 >> 16) ^ a2) << 16);
  else
    result = a2;
  return result;
}

unsigned int __fastcall makeNotShinyIfShiny(unsigned int a1, unsigned int a2)
{
  unsigned int v2; // r2
  unsigned int result; // r0
  int v4; // r1

  v2 = a1;
  result = a2;
  v4 = v2 ^ (v2 >> 16);
  if ( (v4 ^ (result >> 16) ^ result) < 0x10 )
    result ^= 0x10000000u;
  return result;
}

As you can see, the game only forces it to the given shiny state ONLY if it is not already in that state. It is still possible to yield stars and squares, albeit with the usual 1:4096 odds.

kwsch commented 4 years ago

Behavior now mimics the games, and legality checks can now (optionally) flag suspicious PIDs.