The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > ROM Hacking > Research & Development
Sign Up Rules/FAQ Live Battle Blogs Mark Forums Read

Notices

Research & Development Got a well-founded knack with ROM hacking? Love reverse-engineering the Pokémon games? Or perhaps you love your assembly language. This is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!
Research & Development programs in this forum are subject to moderator approval before they are displayed.


Advertise here

Reply
 
Thread Tools
  #1    
Old September 12th, 2011, 07:29 PM
metapod23's Avatar
metapod23
Hardened Trainer
 
Join Date: Mar 2009
Gender: Male
Nature: Timid

Advertise here
This is another thread from me asking experienced ASMers for help

Anyway, I'm curious if it would be possible to add a check in the battle system for when a Pokemon levels up, that would then go to the Evolution Screen if the Pokemon meets the correct level requirements (instead of going to the Evolution Screen only at the end of the battle).

That seems like it would be doable, but I'm not sure if it could be returned to the battle scene easily, and if the battle scene would easily display the newly evolved Pokemon correctly (like its backsprite). And, of course, I've no idea how to begin to do it.

As always, any comments/suggestions or work put into this is appreciated, and credit will of course be given.
__________________
Reply With Quote
  #2    
Old September 19th, 2011, 01:54 AM
miksy91's Avatar
miksy91
A GB/C Rom Hacker since 2010
 
Join Date: Oct 2008
Location: A small country in the North
Gender: Male
Nature: Relaxed
You should start by looking for the pointer that locates the text for pokemon that's evolving. I believe that leads you to the asm routine that is loaded after a wild pokemon or trainer battle ends (checks for pokemon that might evolve, if not --> load map again with some map loading process code).

Besides, the battle ram data might turn "empty" after the battle ends (happens with G/S/C at least) so in that case you should modify the asm code so that the game temporarily stores the whole battle ram elsewhere (and checks if one of the pokemon evolved and modifies its data while at it...).

What you're asking here sounds pretty much "impossible" to be and I wouldn't be the one to try it but with knowledge and a lot of work, it can be done.
__________________
My Rom Hack



Hacks I support





Learn how to hack GB/C games:

Check my GameBoy/Color hacking videos in Youtube
-The video set uses Pokemon Silver (U) rom for demonstrations

Last edited by miksy91; September 19th, 2011 at 01:59 AM.
Reply With Quote
  #3    
Old September 19th, 2011, 03:44 AM
TheDarkShark
Metal Headed Hacker
 
Join Date: May 2010
Location: Germany
Gender: Male
Nature: Calm
I've got another theory: What about looking up the battle ram first, then putting a break on write on your pokemon's level. This should lead you to the routine for level-up the fastest, because you wouldn't need to dig through the routines displaying the text...
__________________
There are two things every Rom-Hacker should learn:
1. Don't give away everything you know!

Reply With Quote
  #4    
Old September 19th, 2011, 01:33 PM
Full Metal's Avatar
Full Metal
C(++) Developer.
Community Supporter
 
Join Date: Jan 2008
Location: In my mind.
Age: 19
Gender: Male
Nature: Timid
Send a message via Windows Live Messenger to Full Metal
I don't believe that there is a way to just modify the existing system for this. What you would have to do is put a branch in the level-up code, check for an evolution ( by branching, again, to the evolution area -- see Jambo51's threads/posts for this. ) and then return. I believe that's it, but it might be a bit more complicated than that. I'm sure that there's lots of checks and balances, and such. But you would also have to re-copy the sprite info, unless you intend to show the evolution animation.
__________________

★ full metal.

I like to push it,
and push it,
until my luck is over.
Reply With Quote
  #5    
Old September 19th, 2011, 01:41 PM
DavidJCobb
RESIDENT RAAAAAAAAAAAAGEMASTER
 
Join Date: Jul 2010
Gender: Male
Nature: Lonely
Quote:
Originally Posted by miksy91 View Post
Besides, the battle ram data might turn "empty" after the battle ends (happens with G/S/C at least)
I don't know about the actual data for enemy Pokemon, but if it's a trainer battle, the arguments passed to the trainerbattle command remains in RAM after the battle.

(All trainer battles go through that command. The effect where a trainer spots and walks to you is actually a "secret" script.)

So OP would need to copy the data for the enemy team -- six 100-byte (0x64) structures, the first of which is located at 0x0202402C. These structures store the full Pokemon data, including stat, health, and status information (with the possible exceptions of confusion and attraction).

The trainerbattle arguments should still be saved in RAM, so OP need only call a (heavily-modified) version of repeattrainerbattle. Modifications would need to be made to ensure that the Trainer sends out the Pokemon they were actually battling with earlier (since Trainers can switch out). (You'll also need to keep track of how many of their four items the Trainer has used, and restore that information upon initiating the battle.)

EDIT: Just in case anyone plans on analyzing battle ASM by looking at the trainer battle commands... Know that "trainerbattle" only prepares a battle -- and then it runs a script that calls "repeattrainerbattle". "Repeattrainerbattle" actually starts the battle (better name woulda been "dotrainerbattle").
__________________
Reply With Quote
  #6    
Old September 19th, 2011, 11:35 PM
Jambo51's Avatar
Jambo51
Glory To Arstotzka
 
Join Date: Jun 2009
Gender: Male
Nature: Quiet
Myself and NintendoBoyDX have actually been researching this, and we came up with a theoretically sound way of doing it.

Our idea was to run the checks in battle right after any level up, and if an evolution trigger was met, basically transform the Pokemon into its evolution. Obviously, we would need to find the stat recalculation routines and make them update the stats, then finally update the stats in the battle ram. As you have no doubt gathered, this will not be a simple process, and indeed, may be improbable as it might make the game lag very badly.

JPAN did research on the evolution animation routines, and found that they only worked when called from exactly where they get called.

Theoretically possible, practically nearly impossible.
__________________
Hey guys, please check out my recreations of the gen 1 and 2 music on my custom engine at my SoundCloud! - Here!
Reply With Quote
  #7    
Old September 19th, 2011, 11:46 PM
DavidJCobb
RESIDENT RAAAAAAAAAAAAGEMASTER
 
Join Date: Jul 2010
Gender: Male
Nature: Lonely
Quote:
Originally Posted by Jambo51 View Post
Obviously, we would need to find the stat recalculation routines and make them update the stats, then finally update the stats in the battle ram. As you have no doubt gathered, this will not be a simple process, and indeed, may be improbable as it might make the game lag very badly.
I suspect that the battle ASM just acts directly on the player's Pokemon data -- the six 100-byte data structures stored at 0x02024284. That's the persistent storage area for the player's party, and immediately preceding it is the storage area used by battle ASM to hold up to six enemy Pokemon.

(My reasoning here is that... If you use "setwildbattle", it prepares the six enemy slots appropriately but doesn't start the battle. You can then modify the Pokemon it loads to the first enemy slot and then call "dowildbattle", and your modifications will remain intact (assuming either that you edited the non-protected stat data, or that you repaired the checksum after editing). The game doesn't back up loaded enemy Pokemon to some special location when it processes a battle, so why would the player's Pokemon be any different?)

So you could just modify the Pokemon; no need to move the data elsewhere, though. The stats in "the battle RAM" are the stats. Now, showing the updated data on-screen is another matter.
__________________
Reply With Quote
  #8    
Old September 20th, 2011, 04:48 AM
Jambo51's Avatar
Jambo51
Glory To Arstotzka
 
Join Date: Jun 2009
Gender: Male
Nature: Quiet
Quote:
Originally Posted by DavidJCobb View Post
I suspect that the battle ASM just acts directly on the player's Pokemon data -- the six 100-byte data structures stored at 0x02024284. That's the persistent storage area for the player's party, and immediately preceding it is the storage area used by battle ASM to hold up to six enemy Pokemon.

(My reasoning here is that... If you use "setwildbattle", it prepares the six enemy slots appropriately but doesn't start the battle. You can then modify the Pokemon it loads to the first enemy slot and then call "dowildbattle", and your modifications will remain intact (assuming either that you edited the non-protected stat data, or that you repaired the checksum after editing). The game doesn't back up loaded enemy Pokemon to some special location when it processes a battle, so why would the player's Pokemon be any different?)

So you could just modify the Pokemon; no need to move the data elsewhere, though. The stats in "the battle RAM" are the stats. Now, showing the updated data on-screen is another matter.
Sadly, your suspicions are incorrect. The game relies on seperate battle data, with some of it being copied from the party data, and some of it being calculated and written from the Pokémon base data in the ROM, during battle.

This data is at 0x02023BE4. There are 4 slots, each 0x58 (88) bytes long.
This is a short list of what i've discovered in the battle data:

0x0 - Species (2 bytes)
0x2 - Stats (12 bytes - 2 bytes per stat)
0x18 - Stat raising/falling trackers (6 bytes)
0x20 - Ability (1 byte)
0x21 - Types (2 bytes)
0x24 - Current PP (4 bytes - 1 byte per attack)
0x28 - Current HP (1 byte)
0x2C - Total HP (1 byte)
0x30 - Nickname (13 bytes)
0x3C - OT Name (8 bytes)
0x54 - Personality Value (4 bytes).

The game links battle data slots to party slots by using the following method:

At 0x02023BC4 is a byte which tells the game which battle slot data to use. Further, it is also used to tell the game which party slot is linked to each battle slot.

The even numbered slots are the player's, while the odd numbered slots are the opponent's.

Starting with 0x02023BCE are an array of bytes which link battle data slots to party data slots.

It works out as such:

Party Slot ID = [02023BC4]*2 + 02023BCE

The byte stored in this location is the party slot of the Pokémon represented by the battle data in slot [02023BC4].

Hopefully this helps.
__________________
Hey guys, please check out my recreations of the gen 1 and 2 music on my custom engine at my SoundCloud! - Here!
Reply With Quote
  #9    
Old September 20th, 2011, 05:01 PM
Full Metal's Avatar
Full Metal
C(++) Developer.
Community Supporter
 
Join Date: Jan 2008
Location: In my mind.
Age: 19
Gender: Male
Nature: Timid
Send a message via Windows Live Messenger to Full Metal
Correct me if I'm wrong, but if we just wanted to evolve the pokemon ( no evolution )
couldn't we just change the byte @ 0x02023BE4.( via an injected routine on exp checking, of course. ) We wouldn't have to call any outside routines, we could just look and see how the original does it, and clip out the parts we don't need. Then force the game to re-lookup the sprite. Blammo. :o
Or am I way way way over-simplifying this? o.O
__________________

★ full metal.

I like to push it,
and push it,
until my luck is over.
Reply With Quote
  #10    
Old September 20th, 2011, 05:50 PM
DavidJCobb
RESIDENT RAAAAAAAAAAAAGEMASTER
 
Join Date: Jul 2010
Gender: Male
Nature: Lonely
Quote:
Originally Posted by Full Metal View Post
Correct me if I'm wrong, but if we just wanted to evolve the pokemon ( no evolution )
couldn't we just change the byte @ 0x02023BE4.( via an injected routine on exp checking, of course. )
You still need to recalculate the stats...

Quote:
Originally Posted by Full Metal View Post
Then force the game to re-lookup the sprite. Blammo. :o
...and then reshow not just the sprite, but also the HP and EXP bars.
__________________
Reply With Quote
  #11    
Old September 21st, 2011, 12:57 AM
JPAN
pokemon rom researcher
 
Join Date: Dec 2008
There are several big problems while trying to implement this. I've been trying to do do this for some time now, more specifically a temporary evolution during battle.

Mine works something like this:
  • Item is used in battle;
  • Party screen shows up, item gets used;
  • Pokemon evolves (now silently), stats get re-calculated;
  • Evolved pokemon appears on screen if it was the one out at the time.
While the data part wasn't that hard to make, the graphical part with the Evolution screen was the one that was giving me me a headache. After I was willing to abdicate the "X is evolving" screen, things went much smoother.

Any change made to your pokemon in the party screen is carried to the battle data as soon as you quit it, and any change made in the battle screen (that has some impact on the Pokemon 100 bytes) will carry to the Party screen as soon as you enter it, or as soon as the battle ends.
Therefore, items used on the party, such as potions, affect the 100 bytes only, and the game engine carries that change by itself to the battle structure. That is why there is only need for one item coding for both situations (Battle-only items like X Attack are the exception, because they change the battle structure directly, and have no effect outside of it).

I created an item that would access the hacked engine's pokemon decrypt function, changed data in it (in this case, pokemon species, but any other field can be changed), encrypt it, and called the game's stat calculator to fix the last 20 bytes of the data. The menu exited and my pokemon was evolved (a squirtle became a blastoise, although still named squirtle, and at level 13).

The reverting part (my case) was done by having a group of 8 flags in memory (only 6 needed) indicating which had evolved using this method, and 8 bytes (your case, 12 needed) Indicating which pokemon to revert to.

Although this time I cannot provide any code (most functions were tested by using breakpoints in VBA+introducing data by hand), know that evolution during battle is possible, and with some studying of the LV up script, it would be possible to evolve a pokemon without calling the evolution screen.
Denying evolution could be implemented by listening directly to the B key in the Input register, and not evolving if pressed.
Changing the battle sprite if it was the pokemon out could be hard, but best bet would be studying the form-change code for Castform, and use that.

PS: The in-game battle stat recalculator is placed at 0x0803E47C in Fire Red, and given in R0 the pokemon slot address, recalculates the ending 20 bytes of the 100byte structure.
__________________
Here are the links for my work


Currently working on:
Battle Script Documentation
Another large project
Reply With Quote
  #12    
Old August 8th, 2012, 02:50 PM
NintendoBoyDX
Togepi
 
Join Date: Jul 2010
Gender: Male
So I've been working on in battle evolution lately. In the end I want to have it set up so that items like stones can be used to get the pokemon to evolve in battle, and also for them to evolve through level up, and any other means.

So one suggestion was to use castforms script, which is at:
Code:
081D92F8
But the problem with castform is that it, and all its forms, are all 1 single image. So there is no opportunity to change the pointer later on.

So I have what I believe is a better idea. Using the ghost "transformation" sequence when the ghost sprite switches to marowak. Because here, one sprite switches completely to another sprite (so it's better than castform) and its not limited to one single move (like the transform attack).

The load of the pointer of marowak's frontsprite is here:
Code:
0800F1C8
I'm currently looking into how its calculated, and all that. Stat calculations and all that is the easy part. But getting the sprite to switch and a viable animation/sound to play is the hard part. Perhaps by looking at this code, a script can be made and hooked into the castform script, which runs at very good intervals.

EDIT :
Well I believe I've figured out a way. Took a few hours, and also thanks to jambo for a lot of info which was helpful in finding the code!

Code:
081D91A1
081D91A1 unk_081D91A1:   .byte 0x39 @ 9          @ DATA XREF: sub_08013514+30o
081D91A1                                         @ ROM:off_08013564o
081D91A2                 .byte 0x20
081D91A3                 .byte    0
081D91A4                 .byte 0x10
081D91A5                 .byte 0x7C @ |
081D91A6                 .byte    1
081D91A7                 .byte 0x3A @ :
081D91A8                 .byte 0x45 @ E
081D91A9                 .byte  0xC
081D91AA                 .byte 0x19
081D91AB                 .byte    0
081D91AC                 .byte    0
081D91AD                 .byte    0
081D91AE                 .byte    0
081D91AF                 .byte 0x39 @ 9
081D91B0                 .byte 0x20
081D91B1                 .byte    0
081D91B2                 .byte 0x10
081D91B3                 .byte 0x7D @ }
081D91B4                 .byte    1
081D91B5                 .byte 0x12
081D91B6                 .byte 0x40 @ @
081D91B7                 .byte    0
081D91B8                 .byte 0x3E @ >
This is the ghost-marowak battle script.

In this script it calls the transformation battle animation in the following way:
Code:
0x45(playanimation)
0xC(bank)
0x19(transformation animation)
0x00000000(a word that can be used for other stuff, but is unused in this case)
There are 0xC banks to choose from for this command. The bank you choose reflects which side receives the animation. So if we just leave the bank as 0xC, I've found the spot that a routine can be hooked in. 0x1 = opponent, 0x0 = player.

Code:
08016EB8 MOVS R0, #1
This spot needs to be changed so that the script can use either 0x1 or 0x0 depending on whether its the player or the opponents move.

Code:
08034C62 BL get_pokemon_data
This spot is where it pulls marowak's ID number out of pokemon main (not battle) ram. This is where we can hook in routines to read and change the ID # of the pokemon, recalculate stats, and all that good stuff.

I'll probably work it out myself soon, or another person can. I also think there must be a better way of doing things, so I'll keep looking into it for sure.

My plan is to:
Spoiler:
1. Change the code in those two routines ^ so that the side who receives the animation can be specified, and the pokemon it changes to can be specified.

2. Hook a script next to the castform script, or perhaps in the level-up routine, to check if a pokemon has the requirements necessary to evolve, and if so play the transform animation and switch the sprite, play some sort of sound, then have the pokemon evolve with full stat recalculations and such.

3. Maintain functionality for the ghost battle... possibly. Personally I don't need it, but a few others may like to have that functionality. There are a lot of checks for the silph scope and ghost battle flags and such that I may have to change, so some testing is in order.

4. Get in battle evolution to work with the items (stones), while maintaining functionality in the overworld.

Later on I might try to find some combination of animations that looks a little better, but for now, the idea is to stick with that transform animation.

Last edited by NintendoBoyDX; August 9th, 2012 at 10:21 PM.
Reply With Quote
  #13    
Old August 10th, 2012, 10:36 AM
Jambo51's Avatar
Jambo51
Glory To Arstotzka
 
Join Date: Jun 2009
Gender: Male
Nature: Quiet
Quote:
Originally Posted by NintendoBoyDX View Post
My plan is to:
1. Change the code in those two routines ^ so that the side who receives the animation can be specified, and the pokemon it changes to can be specified.
Not necessary. If you change the 0xC to a different number, you can specify which Pokémon gets it by writing into one of the many choosable buffers. IIRC, 00 uses 0x02023D6C to get which pokémon to use. You could temporarily store the correct byte into that buffer to get the same effect.

Or better yet, use one of the properly temporary buffers. I can't remember exactly which number uses which, but it is possible.
__________________
Hey guys, please check out my recreations of the gen 1 and 2 music on my custom engine at my SoundCloud! - Here!
Reply With Quote
Reply
Quick Reply

Sponsored Links


Advertise here
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Minimum Characters Per Post: 25



All times are UTC -8. The time now is 08:12 PM.


Style by Nymphadora, artwork by Sa-Dui.
Like our Facebook Page Follow us on Twitter © 2002 - 2014 The PokéCommunity™, pokecommunity.com.
Pokémon characters and images belong to The Pokémon Company International and Nintendo. This website is in no way affiliated with or endorsed by Nintendo, Creatures, GAMEFREAK, The Pokémon Company or The Pokémon Company International. We just love Pokémon.
All forum styles, their images (unless noted otherwise) and site designs are © 2002 - 2014 The PokéCommunity / PokéCommunity.com.
PokéCommunity™ is a trademark of The PokéCommunity. All rights reserved. Sponsor advertisements do not imply our endorsement of that product or service. User generated content remains the property of its creator.