• 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?".
  • 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.

Research: NDS-Style Pre-Battle Mugshots

48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
We've all seen them. Beautifully done custom mugshots, inspired by the ones featured in NDS games. Well, after weeks of work, I'm proud to announce we can finally have them in our game! At least to a limited extent.

Building on Jambo51's earlier work, I managed to finally find the part of the code that doubles the size of the sprite. What's more, I also found the part of the code that controls the 'shape' of the sprite. The end result? With a little hex editing, and Jambo51's Pre-Battle Mugshot hack, we can have NDS-style pre-battle mugshots! Screenshot below:



If someone can point me to where I can find a better mugshot for the Female Player Character/Green, I'd appreciate it!

To have this in your hack, you must first have Jambo51's Pre-Battle Mugshot hack. Then, make the following hex edits:

080D2F38: 00

080D2F82: 00

Next, you need to create a new pointer table for your mugshots and palettes. At the moment, I'm using a modified copy of the Trainer sprite and palette pointer tables. A bit crude, perhaps, but it works!

Find and copy the Trainer sprite pointer table (08023957C) and the Trainer palette pointer table (080239A1C) to free space in your ROM. Then, change the following offsets:

080838E4: XX XX XX 08

080838E0: YY YY YY 08

XX XX XX = Offset of new sprite pointer table in reverse hex

YY YY YY = Offset of new palette pointer table in reverse hex

Due to current limitations, the mugshots are limited to size 64x64. On the bright side, the current setup allows for the player to have a mugshot as well!

Take your 64x64 mugshot, index it using Irfan view, and insert it into the ROM using NSE 2.0. Take note of the palette and image offsets when you insert it. Look up the sprite and palette offsets of the Trainer sprites you want a mugshot for using unLZ GBA or some other program. Scan the respective tables for those offsets, and replace them with the offsets for your mugshot image and it's relevant palette.

NOTE: I highly recommend inserting mugshots for both player characters. Otherwise just their full sprite will appear in the mugshot.

Test it in your game to make sure everything works properly, and you're done!

UPDATE:

Look at what I pulled off!:



That's John Egbert from Homestuck BTW, and no, I didn't make that mugshot. Around the Homestuck fandom, there's this beautiful set of custom Pokemon VS mugshots that have been floating around. A lot of this was motivated by a desire to see those mugshots in a hack. And in extension, the many other custom mugshots some fans make a hobby of making. Never underestimate one driven by the passion of two fandoms.

I still have more work to do before I can release the instructions for doing this. I have to mess with Jambo51's mugshot routine a bit, and make it so both halves of a mugshot assigned to a Trainer will be loaded. Right now, half of the test mugshot is assigned to the player sprite that's always loaded, and will have predictably awkward results if a different Trainer is fought. I also need to make it so it can call the mugshot images from a custom table.

I would also like to see if I can't remove the VS background running along the bottom half, where the player mugshot once was. That's a more distant priority, however.

Comments, questions are welcome!

Credit:
Jambo51-For his original pre-battle mugshot hack
HackMew and Shiny Quaqsire-For their ASM tutorials
knizz-For the Yet Another ASM tutorial, which taught me how to actually find the relevant functions to hack. I highly recommend it alongside HackMew and Shiny Quaqsire's tutorials for would-be ASM hackers.

Ask me about any questions or problems!
 
Last edited:

BrandoSheriff

Has a tendency to figure things out
776
Posts
16
Years
Wow, this is amazing! I was also trying to figure out how the mugshots worked, and I'm glad that this is possible! I'll definitely try this out soon, nice work!
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
Update! I have made significant progress, and it's beautiful! Check the OP for details.
 

Sniper

ふゆかい
1,412
Posts
10
Years
This is a very nice work indeed. I would love to see if you can do more than this, and work on le stuffs. This is very helpful, I also find this one useful. Looking forward to what you can do more to this ;)
 

Dr. Seuss

Will finish GS Chronicles, I swear!
523
Posts
10
Years
Only a little correction, the trainer sprites pointer table as located in 0x23957C, youre missed one digit in the tutorial
And a question ¿how to edit the position of rival mugshot? because in the middle not looks good :/
4326.png
 
Last edited:

BrandoSheriff

Has a tendency to figure things out
776
Posts
16
Years
Nice update! Glad you got the full mugshots to work. I wish I had something to contribute, but college has me swamped. Good luck working out all the kinks! :D
 
2,138
Posts
11
Years
I love that detail for GBA hacks! It makes them more lively!

Do you have any ideas about the canvas size of the Mugshot sprites?

Edit - reread! Sorry about that. 64x64 is a good size.
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
Only a little correction, the trainer sprites pointer table as located in 0x23957C, youre missed one digit in the tutorial
And a question ¿how to edit the position of rival mugshot? because in the middle not looks good :/
4326.png


Oh, thanks, I'll go back and edit that!

Unfortunately, there's no simple way to edit the final position of either mugshot. Scratch that, there is, but there's no real way to figure out how to get the exact result you want. The code that calculates the final position seems to be scattered throughout the routine, and the rival and player positions seem to use different calculations. I got the full mugshot to work by finally getting both mugshots to not move at all, then spending time establishing ideal positions for them.

There are a couple things you can try, but there's no guarantees, speaking as someone who's spent the past few weeks messing with this. Don't be surprised if it requires some trial and error.

At 0xD2ECC, you'll see 20 39. You want to mess with the 20, though I forget which of increasing/decreasing it shifts the final position left/right. This will allow you to adjust the final position, to a limited extent. Reply again if you can't get the needed result, and I'll give you further instructions.

I love that detail for GBA hacks! It makes them more lively!

Do you have any ideas about the canvas size of the Mugshot sprites?

Edit - reread! Sorry about that. 64x64 is a good size.

Yep, 64x64, for now. But once I've worked out how to handle sprite loading, you'll be able to have 128x64 mugshots for opponents (no player mugshots though).
 
Last edited:

Touched

Resident ASMAGICIAN
625
Posts
9
Years
  • Age 122
  • Seen Feb 1, 2018
Why would you have to remove the player mugshot to expand it like that? There are numerous occasions where multiple OAMs are loaded side by side to overcome that 64x64 pixel limitation. You don't need to use the player mugshot to do this: just write a hook that loads more. It's really easy to load additional sprites (and animate/rotate/scale them) once you know how. I've done 64x128 animated sprites for my custom oak intro. Here is the source in question. It should be easy to do it in assembly: no pushing to the stack is required; all the functions use 3 or less arguments.

C Snippet:
Code:
object_load_compressed_graphics(graphics);
object_load_palette(palette);

object_display(top, x, y, 1);
object_display(bottom, x, y + 0x40, 1);

That would load 64x128 pixel sprite as two objects. You could repeat these to make really large objects, but it might be better to do that in C. Basically the entire thing depends on those templates. I've got the offsets for those functions (and more) on my Github. Let me know if you need more info.

EDIT: Mugshot links (don't know if you can use them)
http://greenwithawesome.deviantart.com/art/Red-RBG-FRLG-VS-Sprite-186611749
http://sakuramota.deviantart.com/art/VS-Trainer-Leaf-192477858
 
Last edited:
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
Why would you have to remove the player mugshot to expand it like that? There are numerous occasions where multiple OAMs are loaded side by side to overcome that 64x64 pixel limitation. You don't need to use the player mugshot to do this: just write a hook that loads more. It's really easy to load additional sprites (and animate/rotate/scale them) once you know how. I've done 64x128 animated sprites for my custom oak intro. Here is the source in question. It should be easy to do it in assembly: no pushing to the stack is required; all the functions use 3 or less arguments.

C Snippet:
Code:
object_load_compressed_graphics(graphics);
object_load_palette(palette);

object_display(top, x, y, 1);
object_display(bottom, x, y + 0x40, 1);

That would load 64x128 pixel sprite as two objects. You could repeat these to make really large objects, but it might be better to do that in C. Basically the entire thing depends on those templates. I've got the offsets for those functions (and more) on my Github. Let me know if you need more info.

EDIT: Mugshot links (don't know if you can use them)
http://greenwithawesome.deviantart.com/art/Red-RBG-FRLG-VS-Sprite-186611749
http://sakuramota.deviantart.com/art/VS-Trainer-Leaf-192477858

The reason the player mugshot is removed is because I effectively 'fused' it with the opponent mugshot to make the 128x64 mugshot. And that was because I didn't know how to do precisely what you just told me. I knew it was possible, but with my limited ASM experience I decided to improvise with what I had.

Thank you so much for this! I'll make very good use of it!

EDIT: Oh yes, that Leaf mugshot was exactly was I needed! I wasn't too crazy about the one I was using.

Also, could I have a link to your Github?
 
Last edited:

Touched

Resident ASMAGICIAN
625
Posts
9
Years
  • Age 122
  • Seen Feb 1, 2018
The reason the player mugshot is removed is because I effectively 'fused' it with the opponent mugshot to make the 128x64 mugshot. And that was because I didn't know how to do precisely what you just told me. I knew it was possible, but with my limited ASM experience I decided to improvise with what I had.

Thank you so much for this! I'll make very good use of it!

EDIT: Oh yes, that Leaf mugshot was exactly was I needed! I wasn't too crazy about the one I was using.

Also, could I have a link to your Github?

Here is the Oak Tutorial I've done. https://github.com/Touched/OakTutorial

That's all in C, but its pretty easy to compile (I've given instructions there, and you can just adapt them for a smaller project).

https://github.com/Touched/OakTutorial/blob/master/src/engine/video.h

That's the source file you want. All the offsets for FireRed are in here.
https://github.com/Touched/OakTutorial/blob/master/BPRE.sym

Just call the functions I said with parameters in r0-r3. Otherwise just write in C and save yourself the headache. Let me know if you need more help.
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
Here is the Oak Tutorial I've done. https://github.com/Touched/OakTutorial

That's all in C, but its pretty easy to compile (I've given instructions there, and you can just adapt them for a smaller project).

https://github.com/Touched/OakTutorial/blob/master/src/engine/video.h

That's the source file you want. All the offsets for FireRed are in here.
https://github.com/Touched/OakTutorial/blob/master/BPRE.sym

Just call the functions I said with parameters in r0-r3. Otherwise just write in C and save yourself the headache. Let me know if you need more help.

Oh f*** yes!

Excuse my language, but do you know how many time I've fruitlesly googled 'List of FireRed functions?' This is incredibly useful for me, and it's already helped me get a much clearer picture of the mugshot routine.

I'll give the code you posted a shot, and check back in if I have trouble.
 

Touched

Resident ASMAGICIAN
625
Posts
9
Years
  • Age 122
  • Seen Feb 1, 2018
Oh f*** yes!

Excuse my language, but do you know how many time I've fruitlesly googled 'List of FireRed functions?' This is incredibly useful for me, and it's already helped me get a much clearer picture of the mugshot routine.

I'll give the code you posted a shot, and check back in if I have trouble.

Erm.. Do you have IDA?
https://www.dropbox.com/s/hvvmxxoo1dkmdzc/firered.idb

The most up to date one can be found in knizz's signature. Otherwise you can check shiny quaqsire's stuff: https://github.com/shinyquagsire23/FR-EM-Useful, but everyone gets the function offsets from IDA. I'm gonna be working on updating that resource, because I prefer those separate headers to it all being bundled in one, and the symbol file is a much neater way of doing that. I'll probably add a repo for it on GitHub sometime
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
Erm.. Do you have IDA?
https://www.dropbox.com/s/hvvmxxoo1dkmdzc/firered.idb

The most up to date one can be found in knizz's signature. Otherwise you can check shiny quaqsire's stuff: https://github.com/shinyquagsire23/FR-EM-Useful, but everyone gets the function offsets from IDA. I'm gonna be working on updating that resource, because I prefer those separate headers to it all being bundled in one, and the symbol file is a much neater way of doing that. I'll probably add a repo for it on GitHub sometime

Yes, I have IDA. And I could never get the stupid thing to work properly for me. I'm certain I'm doing something wrong, somewhere, I'll have to try again sometime. But at the moment, I can't get to a point where I can simply browse through functions and such. I use No$GBA's disassembler, consequently.
 

Derlo

Tired....
135
Posts
16
Years
L07o58.png


I found some "offsets" .. maybe useful:

080d2eb2 (0a) = something related to palette
==================================
080d2ecc (20) = initial position img Rival (X axis)
put up to 29 it comes out of screen
==================================
080d2ed2 (02) = height-01 rival
080d2ed8 (2a) = height-02 rival
==================================
080d2ef4 (01) = any other value; the player sprite
becomes the rival, with the x axis inverted!
==================================
080d2efe (88) = initial position of the player sprite (X axis)
put 98 it comes out of the screen and below that inside the screen
below 48 it off the screen.
==================================
080d2f04 (6a) = height of the player
==================================
080d2f18 (22) = any other value crashes after the bars.
==================================
080d2f3a (03) = zoom scale sprites
080d2f7c (3f) = zoom scale sprites
==================================
080d2f4c (1f) = x and y axis of rotation Sprites
10.11.14.15.18.19 - reflection of water (inverted Y and decreases)
12.16.17.1a - invert x axis sprite rival
13 - nothing
==================================
080d2f82 (40) = cut the sprite to be displayed
00:10 - Full sprite
20 ~ - bug
==================================
080dfa0 = (01)
080dfa2 = (03) Controlling x and y axes of the rival sprite
080dfa4 = (03)

080dfac = (01)
080dfae = (03) They control the X and Y axes of the player sprite
080dfb0 = (03)
==================================
080d2fc6 (02) = lengthens and shrinks the rival sprite.
==================================
080d2fde (88) = lengthens and shrinks the player sprite
==================================
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
L07o58.png


I found some "offsets" .. maybe useful:

080d2eb2 (0a) = something related to palette
==================================
080d2ecc (20) = initial position img Rival (X axis)
put up to 29 it comes out of screen
==================================
080d2ed2 (02) = height-01 rival
080d2ed8 (2a) = height-02 rival
==================================
080d2ef4 (01) = any other value; the player sprite
becomes the rival, with the x axis inverted!
==================================
080d2efe (88) = initial position of the player sprite (X axis)
put 98 it comes out of the screen and below that inside the screen
below 48 it off the screen.
==================================
080d2f04 (6a) = height of the player
==================================
080d2f18 (22) = any other value crashes after the bars.
==================================
080d2f3a (03) = zoom scale sprites
080d2f7c (3f) = zoom scale sprites
==================================
080d2f4c (1f) = x and y axis of rotation Sprites
10.11.14.15.18.19 - reflection of water (inverted Y and decreases)
12.16.17.1a - invert x axis sprite rival
13 - nothing
==================================
080d2f82 (40) = cut the sprite to be displayed
00:10 - Full sprite
20 ~ - bug
==================================
080dfa0 = (01)
080dfa2 = (03) Controlling x and y axes of the rival sprite
080dfa4 = (03)

080dfac = (01)
080dfae = (03) They control the X and Y axes of the player sprite
080dfb0 = (03)
==================================
080d2fc6 (02) = lengthens and shrinks the rival sprite.
==================================
080d2fde (88) = lengthens and shrinks the player sprite
==================================

Some of these I knew about (like the initial positions and height), but several of these I hadn't figured out yet. Thank you, I will definitely put these to good use!

I'm still working on this, but school has started, so my progress has slowed significantly. Once I have this figured out for FireRed, I'm planning on figuring out how to import to Emerald, as I have been looking into Emerald hacking.
 

Derlo

Tired....
135
Posts
16
Years
Some of these I knew about (like the initial positions and height), but several of these I hadn't figured out yet. Thank you, I will definitely put these to good use!

I'm still working on this, but school has started, so my progress has slowed significantly. Once I have this figured out for FireRed, I'm planning on figuring out how to import to Emerald, as I have been looking into Emerald hacking.

zFYqke.gif

Okay... I know how is this! ^^'
maybe put some animation in the sprites will be good. I will research this!
 
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
zFYqke.gif

Okay... I know how is this! ^^'
maybe put some animation in the sprites will be good. I will research this!

That's incredible! Can you tell me how you did it? I have a rough idea, but some exact info would be good.
 

Derlo

Tired....
135
Posts
16
Years
That's incredible! Can you tell me how you did it? I have a rough idea, but some exact info would be good.

First change this:
080d2ecc (0x20) = 0x40
080d2ed8 (0x2a) = 0x30
080d2efe (0x88) = 0x98
080d2f04 (0x6a) = 0x2a
080d2f82 (0x40) = 0x00

I use you tut and make my our table...
In the slot 135 (Player ID) put the VS. Img
And for the oponent put the other Img. easy...

In the animated bar I edit the Tileset (0x3F8F60) erasing the border, and change the pallets.
I searching the Raw file of it, when I found will be more easy stylize it.
 
Last edited:
48
Posts
9
Years
  • Age 31
  • Seen Oct 26, 2015
First change this:
080d2ecc (0x20) = 0x40
080d2ed8 (0x2a) = 0x30
080d2efe (0x88) = 0x98
080d2f04 (0x6a) = 0x2a
080d2f82 (0x40) = 0x00

I use you tut and make my our table...
In the slot 135 (Player ID) put the VS. Img
And for the oponent put the other Img. easy...

In the animated bar I edit the Tileset (0x3F8F60) erasing the border, and change the pallets.
I searching the Raw file of it, when I found will be more easy stylize it.

'Animated bar...tileset...'

You're talking about the tileset used for the VS. backgrounds, right? I was looking for that thing!

This is very useful, and will goes a ways in helping refine this. Thanks again!
 
Back
Top