DP - Pokérus manipulation attempts ---------------------------------- INTRODUCTION: Pokérus is known to be harder to manipulate in Diamond/Pearl than it is in Platinum/HeartGold/SoulSilver. Indeed in the latter games, it is depending on overworld RNG which is advancing only through events and thus is easily manipulable. In the former games, it is depending on battle RNG (which also works differently between the two sets of games), but not in the player's advantage. BATTLE RNG: In any Gen IV game, the general idea is the same : > first, the battle is seeded : that means that a special value is either chosen or calculated, and will be used as a reference point for how the battle is going to behave. this seed is also the first value that the battle RNG is going to be. > then, for some fixed action/event, this RNG value will be updated following a specific calculation. (more precisely, if `currRng` is the current RNG value in the fight, the next RNG value will be `currRng * 0x41C64E6D + 0x6073`, omitting the needed 32-bit modulo operations) For all these games, the seed calculation is the same : let's write one seed as 0xABCDEFGH, where each capital letter is a byte (a number from 0 to 15 - or 0 to F in hexadecimal notation) then this seed can be split into 3 different numbers : 0xAB = (month*day + minute + second (+OFFSET) ) % 256 | (the OFFSET is supposed to be 0x4 in DP) 0xCD = hour 0xEFGH = (InGameFramecount % 65536) + (year % 100) | (the InGameFramecount is how many frames have counted by the game since it is booted up) The seeding is performed by the game at a fixed moment after engaging the fight, but depends on the fight type (random encounter, trainer, gym leader, E4 member, Champion, etc). However, Diamond/Pearl RNG is updated every frame during a battle, which is approximately 30 times per second (the theoretical value is ~59.8162/2). POKERUS MANIPULATION: In order for one or several Pokemon to be affected by Pokerus at the end of a fight, the very last battle RNG value should be 2 updates prior to a value which top 4 bytes are either equal to 0x4000, 0x8000 or 0xC000. This nearly always makes the last input of a battle a 1-frame input (at 30fps) in order to acquire Pokérus. The only two near-perfect exceptions are: > 0x40000000 & 0x400067d3, which both allow a strict 2-frame input window. > 0x8000986d & 0xc000c907, which both allow 2 success frames within a 3-frame window. Of course, the progression that a battle RNG follows entirely depends on the seed, which means that such a manipulation comes down to 2 frame-perfect inputs at 30fps. ATTEMPTS AT MANIPULATING POKERUS: (wip - see rough notes below - tools are slowly getting created) - Starting framecounter offset : Based upon several overworld seed manipulations, we'll be able to quantify the number of lost frames when reaching the overworld (or at least, until the seed in generated) -------------------------------------------------------------------------------------------------- RUNNER GAME NDS YEAR A PRESS TIME FRAMECOUNTER ROUGH CALC* OFFSET Craftedite Pearl Any% 2074 1:26.36 0x1382 0x1477 0xF5 " Pearl Glitchless 2098 1:28.77 0x142A 0x151F 0xF5 Werster " 2057 1:32.00 0x14C1 0x15B8 0xF7 Note: "ROUGH CALC" is "A PRESS TIME" * 59.8162 + "NDS YEAR"%100 -------------------------------------------------------------------------------------------------- CONCLUSION : the offset 0xF5 will be retained as the starting framecounter offset. - Overworld offsets : Several events make the IGFramecounter diverge from the console/emulator framecounter. Here is the exhaustive list that matters for 1st encounter Pokérus manip (note that offsets are EMULATOR-referenced frames @60fps) : * Post seed black 12 * Open menu 2 * (Open Trainer Card 15) } Optional since top runners * (Close Trainer Card 15) } don't check their TID * Open Options 6 * Close Options 13 * Close Menu 0 * Mom House 2F->1F 12 * Mom House->Town 14 * THUD textbox 1 * Barry disappearance 2 * Town->Barry house 11 * Barry House 1F->2F 11 * Barry disappearance 1 * Barry House 2F->1F 11 * Barry House->Town 14 * Town->Route 1 } Number of occurrences * (Route->Town 2) } depends on the manip * Barry dialogue 1 * Route->Lakefront 1 * Lakefront->Lake 10 * Lake cutscene 3 * Bag opening 7 * Pokemon Popup 1 * Bag closing 13 * Pre battle seed 2 * (Post battle seed 14) } Doesn't count for the battle seed generation, but worth knowing ---------------------- MANDATORY TOTAL 149 CONCLUSION : Estimated offset for the current Glichless Infernape route = 164 (15 extra due to 5 back-and-forth between Town & Route) - Battle seed offset : Emulators and console are known to differ in transitions length, the former being faster than the latter. This makes the general timings difficult to port from emulator to console. On emulator, the black screen is 37 frames long, the seeding happens on frame 25 (@60 fps) On console, the black screen is ~1.1s (ie ~65 frames) 1st model (linear) : either 25f after the black screen or 12f before the battle (ie 53f) 2nd model (scaled) : generation 2/3rd-1/3rd (ie 44f) We'll assume the 1st model with a seeding before the battle starts = 53 (~0.2s) The delay between the A press and the estimated seeding is approx. 3.8s - Theoretical application to the Infernape Lucky Egg route : The current setup is as follows (from Werster's notes) : Time: 8:57am | May 22nd 2098 Timer: -7.75 (Hit at -1) | Last input at 1:27.7 (Delay 5064, 36 secs, CC08142A) The estimated time for the A input selecting the starter is at ~4:14.0 on Werster's timer, which is ~4:21.75 after setting the NDS time. The battle is nearly always a 2-turn fight, ie. approximately 30s } which will be useful for The estimated time from last textbox to Pokerus check is approx. 3.5s } finding the Pokerus frame setup This leads to the following search space : Hour = 9 Minute = 1 Second = 14-44 (window -10s->+20s accounting for the 3.8s delay from the A press) Month = 5 Day = 22 Year = 2098 IGFramecount = 0x39C0-0x40C2 Barrier for seconds threshold : ~0.55 - Theoretical setups for Infernape Lucky Egg route : SEED SEEDING POKERUS ----------------------------------- Seed 0x83093a3e: 4:12,310 | 34,550s Seed 0x83093a72: 4:13,180 | 27,963s Seed 0x86093b01: 4:15,570 | 31,641s Seed 0x91093db4: 4:27,122 | 28,364s Seed 0x98093f45: 4:33,826 | 32,377s Seed 0x9d09406a: 4:38,725 | 30,571s - Console verifications : LOL good luck ... ------------------------ TESTS SECTION (ignore) : Occidentary + 5 Then + 4 ---- Test on 1/1/2009 c80a70b5 with clock 6:42:14 [0x39] & IGF 290899 [0x7053] & IGT 1:21:43 e00a75fb with clock 6:42:38 [0x51] & IGF 292249 [0x7599] diffs are : 0x18 0x0 0x546 0x18 0x546 1st model : 0x(AB)(CD)(EFGH) AB = month*day + minute + second + 0x8F CD = hour + 0x4 EFGH = IGFramecount + 0x62 ---- Test on 1/1/2009 14067bfb with clock 4:46:00 [0x2F] & IGF 162712 [0x7B98] date + 0xE5 ONLY hour + 2 IGFramecount + 0x63 here ---- Test on 12/12/2099 b60f84b2 with clock 15:09:29 [0xB2] & IGF 33871 [0x844F]