• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[ASM & Hex] Where is the shiny formula stored in Gen 3?

476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
I've been wanting to up the shiny encounter rate in my hack for a long while, but I really don't like using TSK's ShinyCC because it changes the way shininess is determined completely, which means true shinies may not show up as shiny. I want true shinies to keep their shininess in my hack, but still have the encounter of them to be higher, so where is the formula/function for shininess stored? I know that in BW/BW2, there's an offset that has the hex values 08 28, where 08 is how the shininess is determined (it's still 1/8192 because it's technically 8/65536) but one does not simply search for two bites in a ROM and expect that combination to only show up once (I tried that and it came up more than 10 times in the first 1/4 of the ROM). I am using FireRed for my hack but if possible it would be good to know/have the offsets for all the Gen 3 games, just for informational purposes.
 
788
Posts
17
Years
  • Age 29
  • Seen yesterday
For Fire Red, you're looking for the byte at 0x08044120.

If your desired shiny chance is n / 65536, then the byte should be equal to n - 1. For example, the vanilla game has 07 (for 8/65536); if you wanted 16/65536 like the newer games, you'd use 0F.

Edit: To anyone finding this after the fact, you'll also need the changes noted here.
 
Last edited:
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
I think Shinyzer does that.

Shinyzer is based more on recreating the Red Gyarados, but there are ways to *imitate* a higher shiny chance with it - not quite what I'm looking for since I'd need a lot of scripts in each map with wild data.
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
For Fire Red, you're looking for the byte at 0x08044120.

If your desired shiny chance is n / 65536, then the byte should be equal to n - 1. For example, the vanilla game has 07 (for 8/65536); if you wanted 16/65536 like the newer games, you'd use 0F.

Omg you are an actual livesaver! I've been looking for this for so long! Thank you! :D :D :D
 

TaviTurnip

Artist and Streamer | Also a turnip
96
Posts
5
Years
  • Age 33
  • Seen Mar 21, 2024
This is actually useful for me too, haha. What a coincidence that someone would post about this today.

If I can hijack this thread with a very similar question: is there a way in Gen III to give a specific trainer Pok?mon shininess? I've been looking all over the web and found nothing and no trainer-edit tools have a shiny button. Is there an easy byte to edit for this or a place to look for said byte?
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
This is actually useful for me too, haha. What a coincidence that someone would post about this today.

If I can hijack this thread with a very similar question: is there a way in Gen III to give a specific trainer Pok?mon shininess? I've been looking all over the web and found nothing and no trainer-edit tools have a shiny button. Is there an easy byte to edit for this or a place to look for said byte?

This is something you *would* use Shinyzer for.

Here's a tutorial I found a while ago that still works.

https://www.youtube.com/watch?v=5bCg8pJ12hk
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
For Fire Red, you're looking for the byte at 0x08044120.

If your desired shiny chance is n / 65536, then the byte should be equal to n - 1. For example, the vanilla game has 07 (for 8/65536); if you wanted 16/65536 like the newer games, you'd use 0F.

So, another question: Is it possible to reduce the maximum value? IE let's say I wanted more than 255/65536, is it possible to reduce the upper limit of the number to be something like 255/32768 or 255/16384? I know a 1/64 shiny odds is ridiculously extreme and unrealistic but all of my custom mons have shinies and I want the player to have a good chance at getting or seeing them. :)
 
88
Posts
7
Years
  • Age 34
  • Seen Jan 16, 2020
So, another question: Is it possible to reduce the maximum value? IE let's say I wanted more than 255/65536, is it possible to reduce the upper limit of the number to be something like 255/32768 or 255/16384? I know a 1/64 shiny odds is ridiculously extreme and unrealistic but all of my custom mons have shinies and I want the player to have a good chance at getting or seeing them. :)

Yes, but you will probably need assembly knowledge. The formula/comparison looks as follows:
Code:
08044110      lsr r0, r1, #0x10
08044112      ldr r2, [$0804412c] (=$0000ffff)
08044114      and r1, r2
08044116      eor r0, r1
08044118      lsr r1, r3, #0x10
0804411a      eor r0, r1
0804411c      and r3, r2
0804411e      eor r0, r3
08044120      cmp r0, #0x7
08044122      bls $08044134

the cmp r0, #0x7 can only be increased to 0xFF, but you can modify this math formula to alter the numerator and/or denominator as you like.
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
Yes, but you will probably need assembly knowledge. The formula/comparison looks as follows:
Code:
08044110      lsr r0, r1, #0x10
08044112      ldr r2, [$0804412c] (=$0000ffff)
08044114      and r1, r2
08044116      eor r0, r1
08044118      lsr r1, r3, #0x10
0804411a      eor r0, r1
0804411c      and r3, r2
0804411e      eor r0, r3
08044120      cmp r0, #0x7
08044122      bls $08044134

the cmp r0, #0x7 can only be increased to 0xFF, but you can modify this math formula to alter the numerator and/or denominator as you like.

Hmm...I've already edited the numerator (since it's stored as a normal byte) but I have no knowledge of ASM or how to import it. At what point in this routine is the denominator stored?
 
788
Posts
17
Years
  • Age 29
  • Seen yesterday
Hmm...I've already edited the numerator (since it's stored as a normal byte) but I have no knowledge of ASM or how to import it. At what point in this routine is the denominator stored?

It's not. The denominator is implicit in the algorithm. It doesn't literally do a division.
 
88
Posts
7
Years
  • Age 34
  • Seen Jan 16, 2020
Ah, OK, so what exactly would the steps be if I wanted to make the 65536 lower?

For this area of the ROM, you could make a routine that compares r0 to a different register. That would require inserting a hook to your custom code, though. Although this code only changes which palette is loaded, it doesn't actually make the pokemon shiny (aka no shiny star/summary box)

To actually enforce a shiny pokemon, see this
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
For this area of the ROM, you could make a routine that compares r0 to a different register. That would require inserting a hook to your custom code, though. Although this code only changes which palette is loaded, it doesn't actually make the pokemon shiny (aka no shiny star/summary box)

To actually enforce a shiny pokemon, see this

That looks incredibly helpful, but...

a) it only seems to make the encounter rate 1/4096 (like Gen 6+), but by changing the "numerator" via a simple hex edit that we've already seen, I can already make it as high as 1/512, unless I'm just dumb and missing something, which brings me to point b

b) I don't know anything about ASM, how to "compile" it, or how to insert it. Anything ASM (which I'd honestly like to avoid anyway) is literally another language to me, so apologies if I sound really stupid, lol
 
88
Posts
7
Years
  • Age 34
  • Seen Jan 16, 2020
That looks incredibly helpful, but...

a) it only seems to make the encounter rate 1/4096 (like Gen 6+), but by changing the "numerator" via a simple hex edit that we've already seen, I can already make it as high as 1/512, unless I'm just dumb and missing something, which brings me to point b

b) I don't know anything about ASM, how to "compile" it, or how to insert it. Anything ASM (which I'd honestly like to avoid anyway) is literally another language to me, so apologies if I sound really stupid, lol

Unfortunately, you will need assembly to do what you are asking. The routine I linked has two different denominator values (it's for shiny charm). If you want a single, higher shiny rate, just remove the first section, "main", and replace
Code:
normal:
	ldr r0, =(4096)
with ldr r0, =(xxxx), where x is the denominator value you want (1/x)

Check this post for learning how to compile. good luck.
 
71
Posts
6
Years
  • Age 25
  • Seen Jul 11, 2022
For Fire Red, you're looking for the byte at 0x08044120.

If your desired shiny chance is n / 65536, then the byte should be equal to n - 1. For example, the vanilla game has 07 (for 8/65536); if you wanted 16/65536 like the newer games, you'd use 0F.
I just found out changing it to 0x0F causes all Pokemon sprites to appear shiny in the Pokedex.
 
Last edited:
788
Posts
17
Years
  • Age 29
  • Seen yesterday
I just found out changing it to 0x0F causes all Pokemon sprites to appear shiny in the Pokedex.

You also need to change 0x08104A24. This one isn't one less; so change it from 08 to 10 for 16/65536.

Apparently, for the purposes of viewing them in the Pokedex, they're considered to have an OTID of 0 and a personality value of 8. That would result in 8 for the calculation, and guarantee that they wouldn't be shiny under normal conditions. But a result of 8 is shiny under our changed conditions and so they show up shiny.

Edit: Someone pointed out to me that while the Pokemon will show up with their Shiny coloration, they won't have the shiny animation when being sent out or the differently colored frame they're supposed to on the Summary screen. To fix these, you'll need to modify the bytes at 0x080444B0 and 0x080F1776.

They should both be equal to the byte at 0x08044120 ( n - 1 if you want n / 65536 as the chance).
 
Last edited:
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
You also need to change 0x08104A24. This one isn't one less; so change it from 08 to 10 for 16/65536.

Apparently, for the purposes of viewing them in the Pokedex, they're considered to have an OTID of 0 and a personality value of 8. That would result in 8 for the calculation, and guarantee that they wouldn't be shiny under normal conditions. But a result of 8 is shiny under our changed conditions and so they show up shiny.

So if I make the shiny chance 256/65536 (changing the original byte to 0xFF) ...how do I make them not show up as shiny in the Dex? For me personally, it doesn't matter, bu for others that might want more polish, they'd probably want to know :P (more than likely needs ASM afaik)
 
476
Posts
6
Years
  • Age 23
  • Seen Feb 26, 2020
Unfortunately, you will need assembly to do what you are asking. The routine I linked has two different denominator values (it's for shiny charm). If you want a single, higher shiny rate, just remove the first section, "main", and replace
Code:
normal:
	ldr r0, =(4096)
with ldr r0, =(xxxx), where x is the denominator value you want (1/x)

Check this post for learning how to compile. good luck.

Now that I think about it, isn't this just a manual version of TSK's ShinyCC?
 
88
Posts
7
Years
  • Age 34
  • Seen Jan 16, 2020
Now that I think about it, isn't this just a manual version of TSK's ShinyCC?

It seems so. The utility of the assembly code I provided is that you can have different shiny rates, eg. a shiny charm. Not only that, but inserting code yourself means you are in charge of any changes, whereas with a tool you are in the dark with how the changes are being made.
 
Back
Top