Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#26 2013-02-23 21:42:46

RPD490
Member
From: Blackthorn City, Johto
Registered: 2012-09-29
Post 171/259
Website

Re: Change trainer sprites in R/B/Y - request

Might have a slight problem with the Backsprites. I got the same image, using the Manga Design, here is the pic:
http://fav.me/d5009qo

Checked the Backsprites, using PS, they are 56x56.

Offline

#27 2013-02-23 22:18:45

RPD490
Member
From: Blackthorn City, Johto
Registered: 2012-09-29
Post 172/259
Website

Re: Change trainer sprites in R/B/Y - request

Danny-E 33 wrote:

I really encourage you to try this for yourself first. It really isn't too complicated.

Here's what you'll need:
Hexecute
Tile Molester
Tile Layer Pro
Paint

First, let's start with the overworld sprites because they're quite simple.
Open Tile Layer Pro (TLP) and open your ROM that you want to edit.
Scroll down in the ROM so that the offset in the status bar on the bottom says 00014000.
There you will see the player's overworld (OW) sprites.
Select each individual tile and use TLP's tile editor to draw in the hero's new OW sprite. Be careful, the link to the images of the sprite you provided has duplicate OW sprites. The two columns with only two OW sprites are mirrors of other sprites that the ROM doesn't actually need to know since it produces the mirror images itself.
Also remember the order of colors in a palette for RBY are white-light shade-dark shade-black. The default order that TLP uses is backwords so be sure to draw the new sprites appropriately. But you can change TLP's palette yourself in the Palette Editor window which I find very helpful.

Next is the player's front and back sprite.
First open the sprite in paint and make sure to format the picture with the specific parameters.
For the front sprite, the image must be exactly 56x56 pixels and the backsprite but be exactly 32x32 pixels. This means the front sprite is a 7x7 tile image and the backsprite is a 4x4 tile image. A tile is 8 pixels by 8 pixels.
Also, these sprites must include only 4 colors, same as before. White-light shade-dark shade-black. But as long as you use the sprites you already provided, that won't be a problem.
Save that image as a bitmap or a png or something.
Now open up Tile Molester and click the New button.
It will ask you for a size of the new file you are creating. For the front sprite, type 784. For the back sprite, type 256.
Click View->Codec->2bpp planar.
Click View->Block Size->Custom.
For columns, type 1.
For rows, type 7 for the frontsprite or 4 for the backsprite.
Then click Edit->Paste From and choose the image.
At this point, it should be displaying your image exactly the way it's supposed to look like with its original colors. Now double click each color on the palette bar in Tile Molester and change them to match the 4 colors of your image fairly closely. Again, make sure white is on the left!
Then you must click in some empty grey space in the window to finish pasting the image.
This causes any color on the original image to change to the closest matching color from the palette you just customized. If you did this correctly, it should look fairly normal.
Save this file.
Then go to stag019's Pokemon Generation I Graphics Compressor.
For the front sprite, enter 7 for the width and height. For the back sprite, enter 4.
Click Browse and find the file you made in Tile Molester.
Click Go and save that new file.
Open two Hexecute windows.
In one, open your ROM. In the other, open the compressed sprite you just made.
In the ROM, put your cusor right before the byte so that the offset in the status bar at the bottom says 0x12EDE for the front sprite or 0x33E0A for the back sprite.
In the Hexecute window for the sprite, select the whole thing and click Edit->Copy.
In the ROM, press Edit->Paste.

But if your compressed front sprite file was longer than 266 (0x10A) bytes or the back sprite was longer that 144 (0x90) bytes, then don't paste it into the ROM yet. This means your new image is longer than the original player sprite and pasting the new sprite would write over other sprites' data and mess it up entirely. If this is the case for you, just stop here and I'll explain what to do next.
If your new sprite wasn't too big, then you're done! After you've pasted in the new sprite, all you have to do is save.

Let me know any futher clarification you need and I'll try to help you through this.

Actually I do wanna know what to do if the image file is longer than 0x10A, cuz on the Hexacute where my Front Sprite is, it ends at 80 whereas on the ROM it goes on from there adding 800c. When I opened a test ROM since I backup the original file the sprite was garbled, so what should I do?

Offline

#28 2013-03-01 16:54:27

liliebiehlina3siste
New member
Registered: 2013-02-27
Post 1/1

Re: Change trainer sprites in R/B/Y - request

First, thank you Danny-E 33, your post was very useful~

I did everything as you said, the overworld sprite works fine and the Backsprite too, but when I add the frontsprite it just ends up a block of messed pixel...
it seems the sprite's code is too long, what do I have to do to make it work?

Offline

#29 2013-03-03 22:38:19

RPD490
Member
From: Blackthorn City, Johto
Registered: 2012-09-29
Post 179/259
Website

Re: Change trainer sprites in R/B/Y - request

Please note that what she said, she told me and she did everything that I did, but even I don't know what she could be doing wrong. She is also a bit shy talking to others unless someone talks to her first ^^' Anyone know what she could be doing wrong?

Offline

#30 2013-03-04 06:52:24

Danny-E 33
Administrator
Registered: 2012-06-09
Post 423/1,024

Re: Change trainer sprites in R/B/Y - request

RPD490 wrote:

Checked the Backsprites, using PS, they are 56x56.

Your problem with the backsprite is that it needs to be 32x32.

liliebiehlina3siste wrote:

when I add the frontsprite it just ends up a block of messed pixel...
it seems the sprite's code is too long, what do I have to do to make it work?

Having a sprite that is too long shouldn't mess it up in the game. Actually, inserting a sprite that is longer than the original only means it overwrites the data that comes immediately after the original sprite; in this case of the player front sprite, it would mess up the shrinking player sprites that are used in the Oak intro, since this is the data that comes immediately after the player front sprite.

If you put in the new, larger player frontsprite correctly, it should actually work fine. Just that the following sprites would be garbage. So you must have made a mistake somewhere in creating the spite in rgby compressed format or inserted it into the rom incorrectly. It's really hard to tell you what went wrong without a detailed description of what you've done and preferably some screenshots.

Anyway, I really hate to have all this information double posted around the forums, but since you can't do any searching on your own....

Here's my post about repointing sprites (repointing is when you try to use a sprite that has more bytes than the original and you put the sprite somewhere else in the rom and "repoint it" so the game knows where to look for the new sprite):

Danny-E 33 wrote:

Right, here we'll need to learn to repoint data. You never want to put a new sprite where the old sprite used to be if the new sprite has more bytes. You will almost certainly be overwriting important data, like the next sprite, or otherwise completely unrelated data. (in Mew's case, by inserting a larger sprite you have overwritten Mew's base stats, like attack, defense, learnable TMs etc.)
The only instance it would be okay to put a larger sprite in the same place as the original is when you are replacing the Pokemon sprite that is the last one in that bank and is followed by all zeros.

First things first. You need to know what pointers are and how we use them.
A pointer is when the game uses a hardcoded 16-bit address (2 bytes) to "point" to a location in RAM.
Pointers can only point to RAM and never ROM. However, one of the banks in RAM (bank 1) is the switchable bank that is a copy of one of the banks from ROM.
So most simple editing will be done on this RAM bank which is from $4000-$7FFF in RAM.
But pointers are also always little-endian, meaning the "smaller" byte comes first. So all the pointers that we will be dealing with will be from 0040-FF7F, make sense?
But don't forget, pointers can still point anywhere in RAM. Pointers are used for countless things throughout the game. But if we're just repointing sprite data, our data we're pointing to will always be in RAM bank 1, becuase the sprite will always have come from ROM.

Next you need to know how to calculate a pointer when you know the address of the data you are pointing to.
Let's pretend the data we are trying to point to is at 0x27D6B.
First, we want to get the remainder when we divide the address by 0x4000. Taking the remainder of a division problem as the answer is also called modulus division. It is notated by the % sign.
So 0x27D6B / 0x4000 = 0x9 with a remainder of 0x3D6B.
Since all we want is the remainder, this can also be represented by 0x27D6B % 0x4000 = 0x3D6B.
Remember, our pointer had to be between 0x4000-0x7FFF since it is pointing the ROM bank in RAM. So add 0x4000 to the answer you previously got:
0x3D6B + 0x4000 = 0x7D6B
The final thing is making sure we enter our pointer as little-endian. Which means our final, 2-byte pointer to the address 0x27D6B will be 6B 7D.

One more example.
Pointer to the address 0x2BEA9:
0x2BEA9 % 0x4000 = 0x3EA9
0x3EA9 + 0x4000 = 0x7EA9
Little-endian: A9 7E

There are 355 compressed images in the game. 302 Pokemon sprites (front and back), 45 trainer sprites (for the 47 trainer classes. there are two jugglers that use one sprite and the Chief has no sprite), Kabutops fossil, Aerodactyl fossil, Ghost, the player sprite, the two shrinking player sprites that are used in the Oak intro, the player's back sprite, and the Old Man's back sprite.

Now all these sprites already have pointers to their location. All you have to do is modify these pointers when you move the sprite.

The addresses of most of these pointers are pretty well documented. The pointers to a Pokemon's front and back sprites are in that Pokemons' base stats data. The Pokemon base stats data starts at 0x383DE and each entry for each Pokemon is 28 (0x1C) bytes long, and the list is in Pokedex order. The pointer to the front sprite is the 12th and 13th byte of the base stats for a Pokemon and the pointer to the back sprite is the 14th and 15th byte.
That table at 0x383DE has Bulbasaur through Mewtwo in Pokedex order. But Mew's stats are located at 0x425B.
Try to keep a Pokemon's sprite in the same bank as it originally was. If you absolutely have to change the bank a Pokemon sprite is in, let me know.

The pointers for the trainer sprites are bit more confusing. The pointers start at 0x39914, NOT 0x39915 like the Red/Blue:ROM map says. Like always, each pointer is 2 bytes long, but for some reason there are 3 bytes in between each pointer. These pointers are in trainer ID order.
So the first two bytes at 0x39914 is the little-endian pointer to the Youngster's sprite. Then three bytes that I don't know the meaning of. Then the next two bytes are the pointer to the Bug Catcher's sprite. And so on.

The pointer for the Kabutops fossil is at 0x154F. I haven't gotten around to finding the pointers to the Aerodactyl fossil or the Ghost yet, but I wanted to anyway, so I'll find them this weekend and post 'em.

The player's back sprite pointer is at 0x3EC97 and the pointer to the Old Man's back sprite is at 0x3EC9C.

Now the pointer to the player's sprite at the beginning of the Oak intro is at 0x618D.
The pointer to the same sprite after you've named your player a new name is at 0x61C3.
The pointer to the player in your bio (when you select your name in the start menu) is at 0x1349B.
There are possibley other pointers to the player sprite for the other times that sprite is loaded. Such as link battles, or at the end of the Pokemon League when it shows the party you beat the Elite Four with. I don't know if these pointers exist or where they are. I've never had to repoint the player sprite. Meaning, any custom player sprite I've used has been smaller than the original sprite.

That should be everything you need to know. If you have any questions, please ask.

Here's my post about calculating pointers:

Danny-E 33 wrote:

Here's the shortcut I came up with to calculate pointers very simply.
If your address is 0xUVWXYZ:
1. Ignore V and any additional characters to the left.
2. Keep XYZ exactly how they are.
3. If W is a 0, 4, 8, or C make it a 4
    If W is a 1, 5, 9, or D make it a 5
    If W is a 2, 6, A, or E make it a 6
    If W is a 3, 7, B, or F make it a 7
    *(from now on, I'll call this new value "Q" to differentiate it with the original W value)*
4. Make it little-endian: YZ QX
5. IF you need the bank number too, take your initial address minus your big-endian pointer (with the modified W value) and then divide by 0x4000:
(0xUVWXYZ - 0xQXYZ) / 0x4000 = bank number

And since I know you're gonna ask about it next, here's my post about how to customize the bank that the Pokemon sprites are located in:

Danny-E 33 wrote:

If you would like to control what bank the game will look in for each Pokemon sprite, you will need to learn some ASM, which I highly recommend.
You should really start with ASM School to get a feel for ASM first.
And use this as a reference for keeping track of what each opcode does.
Finally, I think this is a great resource for the hex value for each opcode.
Now all this is great, but studying this alone probably won't make you a master at ASM. What really makes light bulbs go off in your head is understanding some real world examples; how ASM is actually put to good use.
So I'm gonna give you this example and hopefully you honestly try to understand and then you can go on to do more great things on your own with ASM.

So let's get started.
There is a routine at 0x1633 that assigns bank numbers to groups of Pokemon ID's. Here is what that original routine looks like:
(note: anything to the right of " ; " is a comment)

ld a, [$CF91] ; this is the RAM address of the internal ID of the Pokemon currently being loaded
ld b, a       ; store Pokemon ID
cp $15        ; check if ID = $15 (Mew)
ld a, $01     ; store bank number for Mew
jr z, $25     ; jump forward 0x25 bytes if z-flag is set (if ID = $15)
ld a, b       ; restore ID into a
cp $B6        ; check if ID = $B6 (Kabutops fossil)
ld a, $0B     ; store bank number for Kabutops fossil
jr z, $1E     ; jump forward 0x1E bytes if z-flag is set (if ID = $B6)
ld a, b       ; restore ID into a
cp $1F        ; check if ID < $1F
ld a, $09     ; store bank number
jr c, $17     ; jump forward 0x17 bytes if c-flag is set (if ID < $1F)
ld a, b       ; restore ID into a
cp $4A        ; check if ID < $4A
ld a, $0A     ; store bank number
jr c, $10     ; jump forward 0x10 bytes if c-flag is set (if ID < $4A)
ld a, b       ; restore ID into a
cp $74        ; check if ID < $74
ld a, $0B     ; store bank number
jr c, $09     ; jump forward 0x09 bytes if c-flag is set (if ID < $74)
ld a, b       ; restore ID into a
cp $99        ; check if ID < $99
ld a, $0C     ; store bank number
jr c, $02     ; jump forward 0x02 bytes if c-flag is set (if ID < $99)
ld a, $0D     ; store bank number
jp $24FD      ; end

Try to get a feel for ASM with the few links I gave you and see if you can understand how this routine works. Let me know if you need any further explination.

Here is a solution for the bank problem created by Sawakita, and then optimized by stag019 and myself.

ld a, [$CF91] ; get Pokemon id
ld b, a       ; store Pokemon id
cp $B6        ; check if id = Kabutops fossil
ld a, $0B     ; store bank of fossil sprite
jr z, $11     ; jump forward 0x11 bytes if z-flag is set (if id = Kabutops fossil)
ld a, b       ; restore id into a
cp $B7        ; check if id = Aerodactyl fossil
ld a, $0D     ; store bank of fossil sprite
jr z, $0A     ; jump forward 0xA bytes if z-flag is set (if id = Aerodactyl fossil)
ld a, b       ; restore id into a
cp $B8        ; check if id = Ghost
ld a, $0D     ; store bank of ghost sprite
jr z, $03     ; jump forward 0x3 bytes if z-flag is set (if id = Ghost)
ld a, [$D0D3] ; load bank from last byte of current Pokemon's base stats
jp [$24FD]    ; end

And the code for that would look like:

FA 91 CF
47
FE B6
3E 0B
28 11
78
FE B7
3E 0D
28 0A
78
FE B8
3E 0D
28 03
FA D3 D0
C3 FD 24

Here, instead of hardcoded bank numbers based on the internal ID, it gets a bank number from the last byte of that Pokemon's base stats data from the table at 0x383DE that I mentioned earlier.
Remember how I said each Pokemon's base stats had 28 (0x1C) bytes? Well, that last byte is always 00 (except for Mew, it is FF) and is certainly never used for anything.
Whenever this routine at 0x1633 is being read, that particular Pokemon's base stats are already copied into RAM, and the last byte is at 0xD0D3.
So in addition to adding this custom routine, you have to go through the 151 Pokemon's base stats and put the sprites bank number into the last byte.
From here, you can easily customize the location of any Pokemon sprite. The only catch is that a Pokemon's front and back sprite must be in the same bank, but that shouldn't be a big deal.

Let me know if any more clerification is needed.

A fair amount of hex editing knowledge is required to understand this, and asm knowledge helps a ton, although it isn't necessary. This isn't a walk in the park, but it is worth it when you fully understand.


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#31 2013-05-10 13:03:57

AvonlyNew
New member
Registered: 2013-05-10
Post 1/2

Re: Change trainer sprites in R/B/Y - request

Hi,
I would like to thank you for earlier help, and ask another question - how put this large backsprite (credit to BurstXShadowzX) in game, and replace violet color on a blue? Danny-E 33 in his "Pokémon Prototype" shows, that it is possible.
Please, same as before, a step-by-step tutorial, because "I haven't a clue, when it comes to these things".
Yours~

/I create a new account, because I can't restore password to older - I lost my e-mail address.

Last edited by AvonlyNew (2013-05-29 20:04:51)

Offline

#32 2013-06-01 02:04:48

Danny-E 33
Administrator
Registered: 2012-06-09
Post 502/1,024

Re: Change trainer sprites in R/B/Y - request

AvonlyNew wrote:

how put this large backsprite (credit to BurstXShadowzX) in game

Well for starters, that back sprite is one pixel too tall. It must be 48x48 pixels.
Second, this thread is even named "Pokemon Red: Backsprites"!! You couldn't do any research on your own??

AvonlyNew wrote:

and replace violet color on a blue?

If you're looking to change the palette used by the back sprite without completely overwriting that palette which is used for a ton of stuff, download Swampert22's PaletteEd GB and read this thread, conveniently named "Pokemon Red: Palettes".......

AvonlyNew wrote:

Please, same as before, a step-by-step tutorial

Seriously, you need to research and read. Everything you have asked this far has been so clearly documented. I'm not double posting all this information all over the board for you again. If you have any specific questions, I will certainly be glad to answer them and help you understand if you are confused by something, but not if you just ask me "how do I do this".


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

#33 2013-06-01 15:57:13

80C
Banned
Registered: 2013-03-16
Post 619/1,257

Re: Change trainer sprites in R/B/Y - request

What About the trainer class Chief?
Could we give an use to it and assign an his own sprite for that trainer class?


I left this forum.

Offline

#34 2013-06-02 17:37:12

Danny-E 33
Administrator
Registered: 2012-06-09
Post 503/1,024

Re: Change trainer sprites in R/B/Y - request

Yes, without any difficulty at all. Just add a sprite in the same bank as all the other trainer sprites, bank 13, and change the appropriate pointer in the list of trainer pic pointers at 0x39914.


Red Hack: Pokémon Prototype

Total number of registered users: 7000+
Total number of active users: ~12

Offline

Board footer

Powered by FluxBB