Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#26 2012-07-06 10:00:14

Danny-E 33
Administrator
Registered: 2012-06-09
Post 36/1,022

Re: Pokemon Red: Backsprites

Thank you stag019 and koolboyman for your support! I will keep trying to get this until I understand. For motivation, I look at what stag019 explained at the beginning of this thread of the simple assembly code that Sawakita wrote to determine the banks of every Pokemons backsprite. I think about how that looked like such a foreign language the first time a read it. And now I understand it crystal clear. I only hope this issue becomes as clear to me with time. I won't give up :)
So here are my thoughts...

So this new routine, that is replacing the routine at 0x3F103, should first load the bank of the backsprite into register a. But the bank is already in register a because RAM 0xD030, which is the last byte of the current Pokemon's base stats and contains the byte of the sprite, was the last thing loaded into register a, right?
Then it needs to uncompress the image found by the pointer that is the 14th and 15th bytes of that Pokemon id's base stats by calling routine 0x24FD, and the uncompressed image is then stored at 0xA188.
Then the length of the uncompressed image (in bytes) needs to be loaded to register pair BC. And that number of bytes needs to be copied from the address in register HL (0xA188?) to the address in register pair DE (0x9310?) by calling routine 0x009D, right?

So I think I understand the gist of the process using words, but what would this look like in asm code?
Also, how do I determine the value to load to register pair BC when each sprite is a different size?
And how should I end the routine? (calling another routine perhaps?)
And please correct me if I made a mistake or forgot something in what I said.

Also, I've been thinking alot about the problem I was having with it not using the correct bank to load the sprites for the fossils and ghost. But I think I have my solution:

stag019 wrote:
; offset 1633
    ld a,[$CF91]
    ld b,a
    cp $15
    ld a,$01
    jr z,.GotBank\@
    ld a,b
    cp $B6
    ld a,$0B
    jr z,.GotBank\@
    ld a,b
    cp $1F
    ld a,$09
    jr c,.GotBank\@
    ld a,b
    cp $4A
    ld a,$0A
    jr c,.GotBank\@
    ld a,b
    cp $74
    ld a,$0B
    jr c,.GotBank\@
    ld a,b
    cp $99
    ld a,$0C
    jr c,.GotBank\@
    ld a,$0D
.GotBank\@
    jp $24FD

Instead, could I use this:

ld a,[$CF91] ;get Pokemon id
ld b,a ;store Pokemon id
cp $B6 ;check if id = Kabutops fossil
ld a,xx ;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,yy ;store bank of fossil sprite
jr z,A ;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,zz ;store bank of fossil sprite
jr z,3 ;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 xx
28 11
78
FE B7
3E yy
28 0A
78
FE B8
3E zz
28 03
FA D3 D0
C3 FD 24

If I'm correct, this will allow me to easily manipulate the bank used for the only three frontsprites that don't have base stats, right? Does anyone see any problems with this new code? I'm going to feel very proud if this works out! :))

Thank you everyone for helping me out with this and getting me started with asm :) I appreciate all your help so much :)

EDIT: Corrected two small mistakes explained further down.

Last edited by Danny-E 33 (2012-07-07 03:51:39)


Red Hack: Pokémon Prototype

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

Offline

#27 2012-07-07 03:12:04

Danny-E 33
Administrator
Registered: 2012-06-09
Post 40/1,022

Re: Pokemon Red: Backsprites

Success! This code worked out beautifully! :))

I know this is a very very simple asm routine (if it's even appropriate to call it that) but nevertheless, I am very proud of coming up with this solution by myself! :)
Again, I thank everyone for being patient when it takes me some time to understand. :)
~Danny-E 33

Last edited by Danny-E 33 (2012-09-23 15:30:41)


Red Hack: Pokémon Prototype

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

Offline

#28 2012-07-07 03:27:25

Miksy91
Member
Registered: 2010-10-16
Post 948/2,305

Re: Pokemon Red: Backsprites

Simplyness is often all you need. I haven't done anything more amazing with Dark Future with asm either but have still gotten the wanted job done. Congrats btw!

"ld a,b ;store Pokemon id" this was wrong in your code but supposedly you just wrote it wrong in the post.

Last edited by Miksy91 (2012-07-07 03:28:45)

Offline

#29 2012-07-07 03:46:50

Danny-E 33
Administrator
Registered: 2012-06-09
Post 41/1,022

Re: Pokemon Red: Backsprites

Miksy91 wrote:

Simplyness is often all you need. I haven't done anything more amazing with Dark Future with asm either but have still gotten the wanted job done. Congrats btw!

"ld a,b ;store Pokemon id" this was wrong in your code but supposedly you just wrote it wrong in the post.

Ah. Of course I meant to write "ld b,a". But the hex value for the opcode I wrote was 47, which is correct so it still worked fine when I put the code into the rom :)

Also, I meant to write "$D0D3". Not "$D030" so I had to correct that mistake in my rom, but nowww it works perfectly :P

~Danny-E 33

Last edited by Danny-E 33 (2012-07-07 03:51:56)


Red Hack: Pokémon Prototype

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

Offline

#30 2012-07-07 05:12:14

Danny-E 33
Administrator
Registered: 2012-06-09
Post 42/1,022

Re: Pokemon Red: Backsprites

kkj1116 wrote:

This is off-topic:

Wow. Looking at all the help posts and threads you've made, and looking at the amount of work you put into solve them (instead of just asking for answers)..
I must say, you inspire me to do better Danny-E 33!

I've been hacking longer than you have (I think) but you know so much more about actual programming with z80 ASM.

I really look forward to Pokemon Protoype. I think you should make a thread for it here so people here could see it.

Wow! Well thank you very much! I have been hacking for about eight months now. I started in November when swampert22 made his return and re-released all his great gen 1 hacking tools. This inspired me to find out how he, or anyone, learned how this data is stored and edited. So I got Hexecute 3.0 RC7 and then i read, read, read, read some more, and then I kept reading. My main motivation to create a rom hack was to correct many mistakes and other things that I just didn't like about the original Red. One thing I didn't like was that there were several Pokemon that you never have the chance to get in Red. At first, I made a very simple hack I called Pokemon Wild Red that had no changes to the story or maps, but every Pokemon could be found at some point in the game and Pokedex completion was possible (to give you a time reference, the making and completion of this "edit" was well before I ever joined here or PC). When I finished this simple edit, I decided there was no point in releasing it to anyone. I knew that I wouldn't diligently play a hack someone else made if the story and all the maps were exactly the same. I couldn't stand playing through the same old game. So I knew I had to learn a ton more to make a hack worth anyone's time and that people would actually beat. So here I am today. I don't care how long this takes. I will finish this project. That's just the mentality I have about things in my life. If I start something that I care about, I will finish it and it will be the best I can make it.

I remember reading that it's frowned upon to make a hack thread here without some sort of of download, so I wasn't going to make a hack thread until the first beta in a few months probably.

And I really don't know thaaat much about z80. But I'm working on it every day. I guess the easy part about it for me is the logic to follow what's happening step by step. And, like I've said a few times now, the only programming language I know really well is for TI calculators. So when I wrote the small routine for determining the bank for the fossils and ghost sprites, I actually wrote it out in my head in TI syntax first and used the equivelant asm opcodes basically.
So for this routine I came up with:

:[$CF91]->a
:a->b
:If a-$B6=0 Then
:1->z
:EndIf
:$0B->a
:If z=1 Then
:Goto gotbank
:EndIf
:b->a
:If a-$B7=0 Then
:1->z
:EndIf
:$0D->a
:If z=1 Then
:Goto gotbank
:EndIf
:b->a
:If a-$B8=0 Then
:1->z
:EndIf
:$0D->a
:If z=1 Then
:Goto gotbank
:EndIf
:[$D0D3]->a
:Lbl gotbank
:Goto [$24FD]

This made it alot easier for me to write the routine accurately. And I'm sure if I never learned calculator programming yeears ago, this whole process would have been a whole lot harder :P Even though all of these TI commands are very basic, learning programming such a long time ago simply gives me an easy understanding of what is going on to get to the end result. Not strictly a better understanding about what each command is and what it does. If that makes any sense.... I guess it's like it helps me see the big picture.
So sure, I've learned alot so far. But I'm nowhere close to done. :) I seriously cannot WAIT to get into college for computer science! This is what I want to do with the rest of my life.
So yeah, this is off topic but now I've told you a bit about myself(:

P.S. Your signature makes me sad... :(

Last edited by Danny-E 33 (2012-07-07 05:26:35)


Red Hack: Pokémon Prototype

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

Offline

#31 2012-07-08 15:53:50

Danny-E 33
Administrator
Registered: 2012-06-09
Post 47/1,022

Re: Pokemon Red: Backsprites

Hmm, I've done more thinking on this, and if I kept the fossil and ghost sprites in the same bank, then I could really shorten the code and I wouldn't have to overwrite register b, because it would never need to recall what the id was. And I only need one jr z command because any one of the three preceeding statements will set the z flag, right?

ld a,[$CF91] ;get Pokemon id
cp $B6 ;check if id = Kabutops fossil
cp $B7 ;check if id = Aerodactyl fossil
cp $B8 ;check if id = Ghost
ld a,xx ;store bank of sprite
jr z,3 ;jump forward 0x3 bytes if z-flag is set
ld a,[$D0D3] ;load bank from base stats
jp [$24FD] ;end

And the code for that would look like:

FA 91 CF
FE B6
FE B7
FE B8
3E xx
28 03
FA D3 D0
C3 FD 24

Does anyone see any problems with this? I think it makes sense, and I'll feel better knowing my code is only as long as it needs to be. I already even had all three sprites in the same bank to begin with, so I thought it was redundant to check, load bank, check, load bank, check, load bank... When it really only needs to check and then load the bank.

Also, does anyone have anymore clerification on the new backsprite loading routine? I still don't have enough knowledge on my own to be able to come up with the routine. I would appreciate it if someone could verify the things that I said and give me a little insight on the questions I asked. Thanks!

EDIT: After thinking about this a little more, is it possible that if the id was B7 (Aerodactyl) and the z flag was set after the cp $B7 command, would cp $B8 unset the z flag? Or does that command only set the flag and not unset it? If it also unsets the flag, then this code is useless :P

Last edited by Danny-E 33 (2012-07-08 16:01:00)


Red Hack: Pokémon Prototype

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

Offline

#32 2012-07-08 17:06:21

481/700

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

Hmm, I've done more thinking on this, and if I kept the fossil and ghost sprites in the same bank, then I could really shorten the code and I wouldn't have to overwrite register b, because it would never need to recall what the id was. And I only need one jr z command because any one of the three preceeding statements will set the z flag, right?

ld a,[$CF91] ;get Pokemon id
cp $B6 ;check if id = Kabutops fossil
cp $B7 ;check if id = Aerodactyl fossil
cp $B8 ;check if id = Ghost
ld a,xx ;store bank of sprite
jr z,3 ;jump forward 0x3 bytes if z-flag is set
ld a,[$D0D3] ;load bank from base stats
jp [$24FD] ;end

No, only the last check will work. cp sets z to 1 if the argument equals a, and sets z to 0 otherwise.

You could try a greater‐than check instead, provided there are no IDs after $B8 that you use:

ld a,[$CF91] ; get Pokémon id
cp $B5 ; check if id ≥ Kabutops fossil
ld a,$xx
jr c,3 ; jump forward 3 bytes if carry is set
ld a,[$D0D3] ; load bank from base stats
jp $24fd

#33 2012-07-09 00:40:14

Danny-E 33
Administrator
Registered: 2012-06-09
Post 48/1,022

Re: Pokemon Red: Backsprites

IIMarckus wrote:
Danny-E 33 wrote:

Hmm, I've done more thinking on this, and if I kept the fossil and ghost sprites in the same bank, then I could really shorten the code and I wouldn't have to overwrite register b, because it would never need to recall what the id was. And I only need one jr z command because any one of the three preceeding statements will set the z flag, right?

ld a,[$CF91] ;get Pokemon id
cp $B6 ;check if id = Kabutops fossil
cp $B7 ;check if id = Aerodactyl fossil
cp $B8 ;check if id = Ghost
ld a,xx ;store bank of sprite
jr z,3 ;jump forward 0x3 bytes if z-flag is set
ld a,[$D0D3] ;load bank from base stats
jp [$24FD] ;end

No, only the last check will work. cp sets z to 1 if the argument equals a, and sets z to 0 otherwise.

Yeah, I realized that was most likely the case after I posted that :P Oh well then.

IIMarckus wrote:

You could try a greater‐than check instead, provided there are no IDs after $B8 that you use:

ld a,[$CF91] ; get Pokémon id
cp $B5 ; check if id ≥ Kabutops fossil
ld a,$xx
jr c,3 ; jump forward 3 bytes if carry is set
ld a,[$D0D3] ; load bank from base stats
jp $24fd

Unfortunately, I'm still using the original id's so the oddish and bellsprout families still come after those three Missingno.s
I have been planning out a huge overhaul to reorganize the Pokemon id's so that they follow Pokedex order. So Bulbasaur would be 0x0, Mew would be 0x96 and those three Missingno.s would follow Mew. That would take alot of careful planning, but if I go through with it, that code would be useable.


Red Hack: Pokémon Prototype

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

Offline

#34 2012-07-14 19:15:39

Danny-E 33
Administrator
Registered: 2012-06-09
Post 56/1,022

Re: Pokemon Red: Backsprites

I'm sorry for double posting without adding anything new to the discussion, but I haven't gotten any closer to solving this problem and I would still appreciate a little more guidance from someone who thinks they understand what key peices of information I am missing. Here is where I'm still at:

Danny-E 33 wrote:

So this new routine, that is replacing the routine at 0x3F103, should first load the bank of the backsprite into register a. But the bank is already in register a because RAM 0xD0D3, which is the last byte of the current Pokemon's base stats and contains the bank of the sprite, was the last thing loaded into register a, right?
Then it needs to uncompress the image found by the pointer that is the 14th and 15th bytes of that Pokemon id's base stats by calling routine 0x24FD, and the uncompressed image is then stored at 0xA188.
Then the length of the uncompressed image (in bytes) needs to be loaded to register pair BC. And that number of bytes needs to be copied from the address in register HL (0xA188?) to the address in register pair DE (0x9310?) by calling routine 0x009D, right?

So I think I understand the gist of the process using words, but what would this look like in asm code?
Also, how do I determine the value to load to register pair BC when each sprite is a different size?
And how should I end the routine? (calling another routine perhaps?)
And please correct me if I made a mistake or forgot something in what I said.


Red Hack: Pokémon Prototype

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

Offline

#35 2012-08-08 08:01:44

Danny-E 33
Administrator
Registered: 2012-06-09
Post 75/1,022

Re: Pokemon Red: Backsprites

Hey everyone. I'm still here and I haven't given up. My hack has made alot of progress and the 6x6 compressed backsprites are inserted into the rom, but I still haven't rerwritten the code at 0x3F103 and the sprites are still being zoomed.

I have a much much stronger understanding of assembly now, but I still feel like theres so much more I need to learn about how RAM works and how the different parts of the engine work for Pokemon specifically.

I feel like there's no way I could write this new routine until I learn more about how the transfer of data works in RAM and how the game is commanded to display things on the screen and other things like this.
Even with my more advanced knowledge of asm which helps, there's obviously so much more about what asm can accomplish that I don't understand. So I feel like me attempting this new routine all on my own is pretty much hopeless.

I want to add support for 6x6 backsprites so badly... And I really reeally need some more guidance, please.
Thank you.


Red Hack: Pokémon Prototype

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

Offline

#36 2012-09-12 04:28:17

Danny-E 33
Administrator
Registered: 2012-06-09
Post 119/1,022

Re: Pokemon Red: Backsprites

So in order to add support for 6x6 backsprites, I need to replace/rewrite the backsprite loading routine at 0x3F103. I figure, the best way to get started should be to get an idea of what the current routine looks like; identify all its parts; decide what should be mimicked and decide what needs to be replaced. So here's the code:

0x3F103

ld a, $CFD9
ld $CF91, a
ld hl, $C405
ld b, $07
ld c, $08
call $18C4
ld hl, $000D
call $1627
ld a, $03
call $3E6D
ld de, $9310
call $16EA
ld hl, $8000
ld de, $9310
ld c, $31
ldh a, $B8
ld b, a
jp $1848

And that's as far as I need to dissasseble because whatever comes next wouldn't be part of this routine?

Well, next I should probably figure out what each command is used for specifically. But I don't know what any of these RAM address are for. The only one that looks familiar is CFD9...
Does anyone want to help me figure this out?


Red Hack: Pokémon Prototype

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

Offline

#37 2012-09-12 05:04:17

Miksy91
Member
Registered: 2010-10-16
Post 1,098/2,305

Re: Pokemon Red: Backsprites

Skip some parts of the code with nops/jr... and you may notice what they're used for.
CF91-CFA3 is the "MEMORY1" ram area for G/S by the way although that may have nothing to do with Red. It's often used to store a 11-byte "name" and according to how this code starts, I don't think Red doesn't use that ram address in the same way.

Last edited by Miksy91 (2012-09-12 05:05:53)

Offline

#38 2012-09-12 11:31:45

Sawakita
Administrator
Registered: 2010-10-16
Post 295/364

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

Well, next I should probably figure out what each command is used for specifically. But I don't know what any of these RAM address are for. The only one that looks familiar is CFD9...
Does anyone want to help me figure this out?

Ok, let's try to break this code down to simple chunks:

ld a, $CFD9
ld $CF91, a

Load the pokemon ID into $CF91 (which is like a "globally used argument", in the sense that other routines require a parameter to be located in this RAM location).


ld hl, $C405
ld b, $07
ld c, $08
call $18C4

$18C4, as you can read in my scripting notes, is a routine that cleans an area of the screen (in other words it fills said area with blank tiles (blank tile ID is $7F)).
Values in b and c specify respectively height and width (in tile units) of the involved area (here we're talking of an area of 7x8 tiles wide).
Value in hl specifies the coordinates: RAM $C3A0 through $C507 is used as a screen buffer. Each byte represents a tile in the screen; to get the tile coordinates from the RAM address (and vice versa) you can use a formula:

RAM ADDRESS to COORDS:
    X = (ADDR - 0xC3A0) % 0x14;
    Y = (ADDR - 0xC3A0) / 0x14);
COORDS to RAM ADDRESS:
    ADDR = 0xC3A0 + X + Y * 0x14;

So, in this case we're going to clean a 7x8 area whose top-left corner is at coords [5, 1] (remember that "everything" is 0-based).


ld hl, $000D
call $1627

Decompress the current pokemon's backsprite into SRAM (value 0x0D is added to the RAM address where base stats is loaded in order to get the correct sprite's pointer: it's 0x0B for the frontsprite pointer, 0x0D for the baksprite pointer [reference]).


ld a, $03
call $3E6D

Call Predefined Routine #03, I have no notes about it, but if I recall correctly it is responsible for the magnification of the sprite.


ld de, $9310
call $16EA

Copy the decompressed sprite from SRAM to VRAM:9310 (frontsprites are loaded in VRAM:9000-930F, while backsprites go into VRAM:9310-961F).


ld hl, $8000
ld de, $9310
ld c, $31
ld a, [$FFB8]
ld b, a
jp $1848

Copy graphics data (I stress the fact that it works on VRAM data because it can only read/write correctly this area during theshort span VBlank interrupt is active) from VRAM:9310 to VRAM:8000, for a total of $31 tiles (i.e. $310 bytes, since each tile is represented by 0x10 bytes). The content of HRAM:FFB8 is copied into b because routine $1848 can copy graphics from any location of the ROM (register b serves the purpose of specifying the bank of data to be copied), but since here we're copying data from VRAM we don't need a bankswitch, although the routine $1848 itself always switch bank; so we pass the current bank (oh, I didn't mention it until now, in R/B VRAM:FFB8 is used to store the current bank's id).

Offline

#39 2012-09-12 15:33:13

Danny-E 33
Administrator
Registered: 2012-06-09
Post 121/1,022

Re: Pokemon Red: Backsprites

So I can't start workin on this til I get home from school, but let's see if I understand this correctly:

So I still want to put the ID of the Pokemon into $CF91.
I still want to clear the 7x8 area with blank tiles.
I still want to decrompress the sprite just the same. But is there a chance there isn't enough bytes reserved for decompressing backsprites to fit a 6x6 image?
Then I would want to exclude the line:

ld a, $03
call $3E6D

so that the original size of the image is kept intact, right?
Then the decompressed sprite should still be moved from SRAM to VRAM the same way. Is there definitely enough space for a larger image now?
Them the sprite is moved within VRAM. You said it copies $31 tiles, but that's already more than enough for a 6x6 image, right? (6x6=$24 tiles)

Hopefully you can clear up anything I misunderstood or wasn't sure about. But I'll go ahead and dive right into this whenever I get home! :D
Thank you so much for trying to help me understand! I'm very thankful I'm this much closer to the answer :)


Red Hack: Pokémon Prototype

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

Offline

#40 2012-09-13 00:38:22

Danny-E 33
Administrator
Registered: 2012-06-09
Post 122/1,022

Re: Pokemon Red: Backsprites

Okay, just clearing out that one line definitely is not the answer. I'm gonna try going through each chunk you pointed out and nop'ing one chunk at at time and observing what happens.

ld a, $CFD9
ld $CF91, a

When I replaced this whole chunk with 00's, Charizard's backsprite loaded just like it normally would.. Why is this code important if Charizard's ID seems to stay in tact?


ld hl, $C405
ld b, $07
ld c, $08
call $18C4

There wasn't anything different when I took this out either.


ld hl, $000D
call $1627

When this was replaced with 00's, Charizards cry still worked, but his sprite was a black square :P


ld a, $03
call $3E6D

This is what you said you believe is for zooming the sprite. When I replaced this with 00's, it was very interesting. All the black pixels of the default player backsprite where in the same place, still zoomed. But now they were Charizard's orange shade since they are not overlapped with the dark blue, so they do not appear black. Then any orange pixel from Charizard was unzoomed, but the image wasn't centered and the bottom got glitchy and inconsistent. And his orange pixels displayed as his dark blue...


ld de, $9310
call $16EA

This simply displayed the default player backsprite with Charizard's palette and Charizard's cry.
This is pretty simple to understand why. It just never copies the uncompressed sprite from SRAM to VRAM, and the player sprite is what's still there.


ld hl, $8000
ld de, $9310
ld c, $31
ld a, [$FFB8]
ld b, a
jp $1848

I took this chunk out except I left the jump command at the end. But it didn't change anything. The sprite loaded just like it always does and played Charizard's cry. How/why is this?


Red Hack: Pokémon Prototype

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

Offline

#41 2012-09-13 00:53:04

stag019
Idea Killer
Registered: 2011-01-05
Post 207/630

Re: Pokemon Red: Backsprites

What I want to know is why is it copied from $9310 to $8000? Also $16EA not only copies the sprite into VRAM, but it also is responsible for the final merger of the two RAM groups (Sawakita should know what I'm talking about since he wrote the compressor).

I'm pretty sure that the magnification happens either somewhere in $16EA or somewhere deep down in the decompression (somewhere after $24FD). I'm thinking it's probably the former though...


You can try to hide yourself in this world of pretend; when the paper's crumpled up, it can't be perfect again.

Offline

#42 2012-09-13 10:35:03

Sawakita
Administrator
Registered: 2010-10-16
Post 296/364

Re: Pokemon Red: Backsprites

Let's cut this short. I gave it a shot at rewriting the code not to use magnification.

ROMF:7103 fa d9 cf         ld   a,(cfd9)
ROMF:7106 ea 91 cf         ld   (cf91),a
ROMF:7109 21 05 c4         ld   hl,c405
ROMF:710c 06 07            ld   b,07
ROMF:710e 0e 08            ld   c,08
ROMF:7110 cd c4 18         call 18c4
ROMF:7113 21 0d 00         ld   hl,000d
ROMF:7116 cd 27 16         call 1627
ROMF:7119 cd c8 7b         call 7bc8
ROMF:711c 00               nop
ROMF:711d 00               nop
ROMF:711e 00               nop
ROMF:711f 00               nop
ROMF:7120 00               nop
ROMF:7121 00               nop
ROMF:7122 00               nop
ROMF:7123 00               nop
ROMF:7124 21 00 80         ld   hl,8000
ROMF:7127 11 10 93         ld   de,9310
ROMF:712a 0e 31            ld   c,31
ROMF:712c f0 b8            ld   a,(ff00+b8)
ROMF:712e 47               ld   b,a
ROMF:712f c3 48 18         jp   1848

ROMF:7bc8 3e 44            ld   a,44    ; backsprites are 4x4 tiles
ROMF:7bca 11 10 93         ld   de,9310 ; destination
ROMF:7bcd d5               push de      ; this is a hack needed in the code we're jumping to
ROMF:7bce c3 70 16         jp   1670

I tested this code, and it works fine. Notice that this code works just for the pokemon' backsprites (although I have to admit it's a bit hacky, in fact the jump to $1670 doesn't go to the beginning of a routine). The trainer's backpic is loaded in another routine.
The jump to $1670, in fact, is in the middle of a routine that was originally written to centre frontsprites (as you already know sprites can be 5x5, 6x6 or 7x7 tiles, but the end result in VRAM is always a 7x7 wide sprite). This routine actually starts at $1665 and is the code that handles frontsprites' decompression (through a call to subroutine $1627) and display. Since it doesn't expect a backsprite I had to skip the first part where it looks for the frontsprite's pointer and its size (stored at WRAM:D0C2). Hardcoding the backsprites' size is not ideal, but considering they're all going to be the same size (I guess that's your plan too, right?) I suppose it's not going to be a problem.
So, we jump at $1670 faking a routine that centre our 4x4 (or whatever size your going to use, just loading a value in a before the jump)
backsprites, then the bit-layers are inteleaved, and finally the assembled
sprite is loaded into VRAM.

Now, you should have a more clear view of some of the routines that handle front-/back- sprites. Implementing the new behaviour for the trainer's (and the old man, if that matters) backsprites should be easier, once you have figured out pokemon's backsprites.


stag019 wrote:

What I want to know is why is it copied from $9310 to $8000?

I have no idea.

stag019 wrote:

I'm pretty sure that the magnification happens either somewhere in $16EA or somewhere deep down in the decompression (somewhere after $24FD). I'm thinking it's probably the former though...

No it doesn't. As I said, the magnification happens inside Predefined Routine #03. The decompression has nothing to do with the magnification. Although I don't feel like posting here the whole code with comments, I post routine $16EA with comments, check this out:

ROM0:16ea af               xor  a
ROM0:16eb ea 00 40         ld   (4000),a    ; enable SRAM
ROM0:16ee d5               push de          ; save dest for later
ROM0:16ef 21 97 a4         ld   hl,a497     ; end of composed sprite
ROM0:16f2 11 0f a3         ld   de,a30f     ; end of 2nd bit-layer
ROM0:16f5 01 87 a1         ld   bc,a187     ; end of 1st bit-layer
ROM0:16f8 3e c4            ld   a,c4        ; 0xC4 = 7 * 7 * 4
ROM0:16fa e0 8b            ld   (ff00+8b),a
ROM0:16fc 1a               ld   a,(de)      ; intertwin the two layers
ROM0:16fd 1b               dec  de
ROM0:16fe 32               ldd  (hl),a
ROM0:16ff 0a               ld   a,(bc)
ROM0:1700 0b               dec  bc
ROM0:1701 32               ldd  (hl),a
ROM0:1702 1a               ld   a,(de)
ROM0:1703 1b               dec  de
ROM0:1704 32               ldd  (hl),a
ROM0:1705 0a               ld   a,(bc)
ROM0:1706 0b               dec  bc
ROM0:1707 32               ldd  (hl),a
ROM0:1708 f0 8b            ld   a,(ff00+8b)
ROM0:170a 3d               dec  a
ROM0:170b e0 8b            ld   (ff00+8b),a
ROM0:170d 20 ed            jr   nz,16fc     ; check if intertwining is complete
ROM0:170f fa aa d0         ld   a,(d0aa)    ; check if sprite requires
ROM0:1712 a7               and  a           ; mirroring
ROM0:1713 28 0e            jr   z,1723      ; else go copying sprite to dest
ROM0:1715 01 10 03         ld   bc,0310
ROM0:1718 21 88 a1         ld   hl,a188
ROM0:171b cb 36            swap (hl)
ROM0:171d 23               inc  hl
ROM0:171e 0b               dec  bc
ROM0:171f 78               ld   a,b
ROM0:1720 b1               or   c
ROM0:1721 20 f8            jr   nz,171b
ROM0:1723 e1               pop  hl          ; recover dest (former "de")
ROM0:1724 11 88 a1         ld   de,a188
ROM0:1727 0e 31            ld   c,31
ROM0:1729 f0 b8            ld   a,(ff00+b8)
ROM0:172b 47               ld   b,a
ROM0:172c c3 48 18         jp   1848        ; copy sprite from SRAM:A188 to "dest"

As  you can see, $16EA is responsible for intertwining the two bit-layers, integrating a possible mirroring, launching the upload to VRAM, and nothing else.
Routine $1665, which is the one that calls $1627 (and $24fd through $1627) and $16ea, doesn't have any role in sprite magnification either.
All the magnification happens inside Predef_03. The non-trivial thing is that you cannot simply remove it and have a well-arranged sprite; some teaking is required as I showed you in the first part of this post.

Offline

#43 2012-09-14 01:25:29

Danny-E 33
Administrator
Registered: 2012-06-09
Post 123/1,022

Re: Pokemon Red: Backsprites

Wow! That's genius :o
I got this working without any problems at all :)

Here it is! :D

inE2uEe.png

My next question is, where is the routine that loads the player back sprite? Then maybe I can recreate this on my own :)

Last edited by Danny-E 33 (2013-06-08 11:10:46)


Red Hack: Pokémon Prototype

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

Offline

#44 2012-09-14 04:36:01

stag019
Idea Killer
Registered: 2011-01-05
Post 208/630

Re: Pokemon Red: Backsprites

Here's what I've been wanting to see for a long time.

gengar_v_nidorino.png

P.S. I won the battle, Gengar is always better than Nidorino.


You can try to hide yourself in this world of pretend; when the paper's crumpled up, it can't be perfect again.

Offline

#45 2012-09-14 15:45:22

Danny-E 33
Administrator
Registered: 2012-06-09
Post 124/1,022

Re: Pokemon Red: Backsprites

kkj1116 wrote:

But in the intro sequence somehow Tackle/Body Slam/Struggle affects Ghost types.

Hahaha, I've never thought about that before :P


Red Hack: Pokémon Prototype

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

Offline

#46 2012-09-15 10:47:55

Sawakita
Administrator
Registered: 2010-10-16
Post 297/364

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

My next question is, where is the routine that loads the player back sprite? Then maybe I can recreate this on my own :)

The routine starts at 0x3EC92. Do you need some more info about that routine too?

bgb00001.png
A giant Sandshrew.

stag019 wrote:

gengar_v_nidorino.png

P.S. I won the battle, Gengar is always better than Nidorino.

kkj1116 wrote:

But in the intro sequence somehow Tackle/Body Slam/Struggle affects Ghost types.

I always thought it was a Snorlax (or a Drowzee).

Offline

#47 2012-09-15 18:33:28

Danny-E 33
Administrator
Registered: 2012-06-09
Post 127/1,022

Re: Pokemon Red: Backsprites

Sawakita wrote:

The routine starts at 0x3EC92. Do you need some more info about that routine too?

bgb00001.png
A giant Sandshrew.

I'm not sure yet. Hopefully I can figure it out on my own at this point :) but I'll have to take a look at it tonight. I'm about to leave for my first marching band competition this year! :D

Sawakita wrote:

I always thought it was a Snorlax (or a Drowzee).

Hmm.. I guess it probably is a Snorlax.. I guess just cause it's purple, we all assumed it was a Gengar :P


Red Hack: Pokémon Prototype

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

Offline

#48 2012-09-15 22:50:41

stag019
Idea Killer
Registered: 2011-01-05
Post 210/630

Re: Pokemon Red: Backsprites

Guys, it really is Gengar. Everyone keeps saying that it only sorta looks like him (comet pointing out the lack of back spikes and having claws) but that's more because the inconsistency in the sprites to begin with (see also upside down Koffing). As kkj1116 pointed out, it's Gengar in FireRed/LeafGreen, as well as the first episode of the anime. Plus Gengar and Nidorino's feud goes way back to 1990.


You can try to hide yourself in this world of pretend; when the paper's crumpled up, it can't be perfect again.

Offline

#49 2012-09-16 19:54:12

Danny-E 33
Administrator
Registered: 2012-06-09
Post 130/1,022

Re: Pokemon Red: Backsprites

Gah, I can't get a stupid breakpoint to work at 0x3EC92...

I put a read/write/execute breakpoint at 0F:6C92. That's right, right?


Red Hack: Pokémon Prototype

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

Offline

#50 2012-09-17 16:45:52

Sawakita
Administrator
Registered: 2010-10-16
Post 298/364

Re: Pokemon Red: Backsprites

The only way you can interrupt the code flow at a certain address by using access breakpoints (at least as far as I know) is by enabling the "on jump" flag: and even in this case you're not breaking on the address you're looking for, but instead you're breaking on the operation that calls/jumps to that address (e.g. if you set an access breakpoint (using the "on jump" flag) to, say, $251A, you'll break at $2510 where the code is "call $251A").


The "right way" is instead that you use "Debug > breakpoints" instead of "Debug > access breakpoints". The former is for interrupting the code flow at a certain address (and/or on a certain condition, for example when a certain value is loaded in a). The latter is normally for interrupting access on RAM.

Last edited by Sawakita (2012-09-17 16:46:27)

Offline

Board footer

Powered by FluxBB