Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2012-06-14 20:10:06

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

Pokemon Red: Backsprites

Hello, I'm new to the Skeetendo forums and I'm working on a hack of Pokemon Red. But I need a bit of help:

In my hack, I am replacing all of the sprites with sprites from GSC and they are all comressed using RBY compression. I don't have a problem with the front sprites and they are working great. But the back sprites are giving me a bit of trouble. In Pokemon Red, back sprites are originaly 4 tiles x 4 tiles, and GSC backsprites are 6x6. When I insert a new backsprite ontop of the old one, the image looks like this:

m2MHmew.png

Then I tried repointing the frontsprite to the backsprite data just to make sure the data was correct and I got this:

rXcSYPk.png

So I know I entered the code correctly. I also changed the first byte of the image to 66 instead of 44 originally. I'm assuming this is happening because there is no byte describing the size in the Pokemon's base stats (starting at 383DE) because there is no need to state the size if every sprite is 4x4, unlike the frontsprite which has a byte (55, 66, 77) right before the pointer which matches the first byte of the sprite image data itself. Is there a way for the game to know it's decompressing a 6x6 sprite rather than a 4x4 sprite?

Also, since I'm replacing every sprite, and they are compressed, the frontsprites take up about just as much space as they did originally. But since the backsprites were 4x4 images and now they're 6x6 images they take up alot more room. Once I replace enough of the sprites of a certain bank, and the data has been shifted down, I'm sure I will run out of room for the 50+ sprites per bank because of the extra needed room for the backsprites. So my problem is that once I move a sprite to a new bank, there is no byte in the base stats immediately by the pointers to the sprites to determine which bank the sprites are in. I have a very good understanding of pointers now, but I am unsure how to modify which bank is loaded to $4000-$7FFF of RAM memory to fit the new sprites location.

Anyone's help would be greatly appreciated! :)

~Danny-E 33

Last edited by Danny-E 33 (2012-12-01 12:50:42)


Red Hack: Pokémon Prototype

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

Offline

#2 2012-06-14 21:08:10

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

Re: Pokemon Red: Backsprites

Out of curiosity, what are you using for this? My tool, Sawakita's tool, or maybe even your own tool or doing them by hand?

Either way, I can help solve one of your problems, and can partially explain the other, but not solve it. However, I'm curious to the solution too.

There's code in the assembly that basically reads like this (this is an example, I'm too lazy to find the real code or real numbers):

if(id<8) use bank 5; elseif(id<55) use bank 6;

etc. Instead, Sawakita wrote a small piece of assembly code that skips over that check, and instead just uses the last byte in the base stats data structure (which is always 00 except for Mew where it's FF, but it's almost certainly unused).

ROM[0x1634] = 0xD3;
ROM[0x1635] = 0xD0;
ROM[0x1637] = 0xC3;
ROM[0x1638] = 0xFD;
ROM[0x1639] = 0x24;

Which basically means at ROM address 0x1634 put a byte of 0xD3, etc.

Then, you can use any of the empty banks at the end to put the compressed graphics in (the frontpics and backpics must be in the same bank, but that isn't a big deal).

As far as the first part of your post, it's working that way because, like you said, the backpics are 4x4 tiles => 32x32 pixels. However, the bottom and right 4 rows of pixels are unused. This leads to 28x28 pixels used, which the engine then scales by 2x using the simple nearest-neighbor interpolation algorithm, resulting in a 56x56 pixel image (which is 7x7 tiles). What we would need to do is figure out where the scaling code is and jump around it. I might look to see if this is already in the disassembly, and if so, if I can do it right.


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

Offline

#3 2012-06-16 06:08:28

Danny-E 33
Administrator
Registered: 2012-06-09
Post 2/1,023

Re: Pokemon Red: Backsprites

Hmm... So you're saying that all I need to change is 0x1634, 0x1635, 0x1637, 0x1638, and 0x1639's byte to D3, D0, C3, FD, and 24 respectively to be able to use each Pokemon's last byte of their base stats as an indicator of the bank that their front and back sprites are located in? Interesting... And correct me if I misunderstood
And we're sure that even though Mew's last byte of base stats is FF it still has no use?

And I feel like I mostly understood what you explained about the other problem, but I don't know where to go with this information :P I'm sure Sawakita would be great help with this problem if he was around... Or if Koolboyman was willing to offer his assistance. All of your investigation into this problem is extremely generous of you and I highly appreciate it :)

FYI, I have a very poor understanding of assembly, but I would loove to change that. For the record, I am very clever with programming on a TI Voyage 200, however, I'm not sure if that would be applicable :P

And to answer your question, I have been using your tool. It is simply amazing. It took me a while to get it to work for the first time, but after I found your post of how to make gameboy 2bpp binary files in Tilemolester, I haven't had any problems at all. It has been so extremely useful. I want to personally thank you for writing such a flawless program and taking the time to understand the complicated decompression routine that I could never wrap my mind around no matter how many times I read Tauwasser's guide... :P and I believe I messaged you on Pokecommunity asking how to make 2bpp files and then messaged you again whenever I found your post on Skeetendo about Tilemolester :P


Red Hack: Pokémon Prototype

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

Offline

#4 2012-06-16 18:44:38

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

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

FYI, I have a very poor understanding of assembly, but I would loove to change that. For the record, I am very clever with programming on a TI Voyage 200, however, I'm not sure if that would be applicable :P

Well good, we can work on this a little then.

Danny-E 33 wrote:

Hmm... So you're saying that all I need to change is 0x1634, 0x1635, 0x1637, 0x1638, and 0x1639's byte to D3, D0, C3, FD, and 24 respectively to be able to use each Pokemon's last byte of their base stats as an indicator of the bank that their front and back sprites are located in? Interesting... And correct me if I misunderstood
And we're sure that even though Mew's last byte of base stats is FF it still has no use?

Yes, exactly. Here is the code that originally determined the bank.

; 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

The first line puts the Pokemon's id number into register "a".  The second line copies it into "b". "cp" means "compare", which just compares a against whatever follows it (in the first case, $15, or Mew). A comparison is done by subtracting the operand ($15 in this case) from "a", setting the flags but leaving "a "alone. It then puts $01 (the bank Mew's picture is in), into "a". "jr z,.GotBank\@" means it jumps to the code labelled "GotBank\@" if the result (a - $15) is zero (only true for Mew). If at any point it jumps to the label (which then simply jumps to the decompression routine), the rest of the code in between is never accessed. It then reloads the Pokemon's id from b back into a.

The last 3 commands are repeated again, this time for Pokemon id $B6 (the Kabutops fossil) with bank $0B. The commands continue to repeat, but rather than "jr z,.GotBank\@", the line is "jr c,.GotBank\@", which means if the comparison/subtraction results in a "carry" (which will only happen if "a" is less than the operand) then it will jump to the label.

Keep in mind I'm not just trying to explain this to you, I'm trying to explain it to myself since I'm not that hot at assembly either.

Anyways, when you make the changes I listed in my last post, here's what you end up changing it to:

; offset 1633
    ld a,[$D0D3]
    ld b,a
    jp $24FD

$D0D3 is the location in the RAM where the unused last byte of the base stats data structure lies. It then copies this into b and then jumps straight into the decompression routine.

Danny-E 33 wrote:

And I feel like I mostly understood what you explained about the other problem, but I don't know where to go with this information :P I'm sure Sawakita would be great help with this problem if he was around... Or if Koolboyman was willing to offer his assistance. All of your investigation into this problem is extremely generous of you and I highly appreciate it :)

Yeah I don't see this code in the disassembly anywhere and so unless I'm lucky enough to find it myself (which I don't have the time right now getting ready for work), then one of those two would be our best bets. I know Koolboyman has done it before (see also Brown version).

Danny-E 33 wrote:

And to answer your question, I have been using your tool. It is simply amazing. It took me a while to get it to work for the first time, but after I found your post of how to make gameboy 2bpp binary files in Tilemolester, I haven't had any problems at all. It has been so extremely useful. I want to personally thank you for writing such a flawless program and taking the time to understand the complicated decompression routine that I could never wrap my mind around no matter how many times I read Tauwasser's guide... :P and I believe I messaged you on Pokecommunity asking how to make 2bpp files and then messaged you again whenever I found your post on Skeetendo about Tilemolester :P

Heh, thank you. But don't just thank me, Tauwasser helped me understand his guide and without it and his personal help I /never/ would have been able to do this. I'd like to try to rewrite his guide sometime into something slightly easier to understand, as well as maybe add psuedo-code example to help explain it. And maybe even go through a simple sprite, step by step, to show how it's done. I'd really like to try to turn my online tool into an actual tool, but I'm not as hot with programming languages as I am with scripting languages (especially PHP). That and it's been so long I'm not even sure how much of this I can remember. Oh also I check here every day but I haven't been on Poke-communist-ity in a while so if you want to contact me here is the better option.

Last edited by stag019 (2012-06-16 18:47:24)


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

Offline

#5 2012-06-20 15:35:56

Danny-E 33
Administrator
Registered: 2012-06-09
Post 3/1,023

Re: Pokemon Red: Backsprites

Hmmm, well pretty much everything you said about the asm side of the problem you fixed I don't understand... but I trust you :P
And as far as stopping the game from 2x zooming the 3.5x3.5 tile backsprites to produce a 7x7 image... I wouldn't know how to figure out the answer on my own and Sawakita hasn't been online in a long time as far as I'm aware. I've messaged Koolboyman about this but it doesn't seem like he's gonna reply, but I know he's a very busy man. Is there anyone who can contact him who perhaps Koolboyman will respond to a little more swiftly? :P Otherwise, what can we all do to put our heads together and figure this one out?


Red Hack: Pokémon Prototype

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

Offline

#6 2012-06-25 06:16:12

Danny-E 33
Administrator
Registered: 2012-06-09
Post 5/1,023

Re: Pokemon Red: Backsprites

So I've read the first couple lessons of "ASM School" and I understood more than I thought I would! :D
Now I reread your post about what the peice of code originally did, and what it'll do after the changes and it actually made sense! :O The only thing is that I didn't fully understand is what "jr (z/c),.GotBank\@" is refering to.. Could you expand on that a little? Anyway, do you have any advice on where I could begin with locating what string of code is responsible for zooming the backsprites? I would be thrilled if we could figure this out! :) thanks for all your help.


Red Hack: Pokémon Prototype

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

Offline

#7 2012-06-25 15:28:09

Miksy91
Member
Registered: 2010-10-16
Post 937/2,308

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

The only thing is that I didn't fully understand is what "jr (z/c),.GotBank\@" is refering to.. Could you expand on that a little? Anyway, do you have any advice on where I could begin with locating what string of code is responsible for zooming the backsprites? I would be thrilled if we could figure this out! :) thanks for all your help.

I believe there is a complete guide for all GB assembly commands in romhacking.net (I believe, not sure if I get mine from there or not).
To answer your question though,

jr xx (jump xx bytes ahead in code)
jp xxyy (jump to address determined by pointer xxyy) (just for reference)
jr z xx (jump xx bytes ahead if z flag is set)
jr nz xx (jump xx bytes ahead if z flag is not set)

z flag = "zero flag" which is often (or possibly always) set when two register values (or register and a determined hexadecimal digit) match with each other (cp a,b; or a,b) but there are other cases as well.
c flag = "carry flag" (I don't understand in which cases this is set/unset but you could try to look for that guide I mentioned).
And again, jr c xx (if carry flag set, jr xx) and jr nc xx (if carry flag not set, jr xx).

Can't say anything for your second question though.

Last edited by Miksy91 (2012-06-25 15:30:33)

Offline

#8 2012-06-25 19:42:19

Danny-E 33
Administrator
Registered: 2012-06-09
Post 6/1,023

Re: Pokemon Red: Backsprites

Thanks for clearing that up :) it feels kinda cool speaking in asm and understanding what is going on for once :DD haha.
Now, I don't know how to use bgb as a debugger yet, but would that be at all useful for figuring out the routine that zooms the backsprites? I have no idea if that is a dumb suggestion or not :P I just want to do everything in my power to figure this one out, as there is no documentation on this matter, that I can find. I'm sure we can do it if we just keep trying :)

Last edited by Danny-E 33 (2012-06-25 19:43:13)


Red Hack: Pokémon Prototype

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

Offline

#9 2012-06-27 15:19:02

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

Re: Pokemon Red: Backsprites

Hello, sorry for not having been around for a while.

Now, regarding the question: The routine that loads the monsters' backpics starts at address 0x3f103.
For those who are interested it's pointed by the fifth (although its ID is 0x04 since arrays are 0-based) 3-byte-pointer of the PredefPointers (in the linked page, you can do a quick Ctrl-F search for "PredefPointers:" to find the table, since the file is large).

What I did for my hack is repointing that routine to another one I wrote (you can get all the code at my pokewood repository; again, you can Ctrl-F "MagnifyBackPic_hacked:", to find the main code). Consider that the code I wrote there is one of my first attempts at ASM coding, and at the time I was even still coding right on the ROM (instead of assembling-linking my code the right way) that's way it's such a spaghetti-mess. Also that specific routine relies on several other hacks I made in that ROM (including arranging pics' bank locations into arrays, unlike the original hardcoded banks).

Anyway my suggestion is that you replace the 5th 3-byte pointer of the previously mentioned table with a 3-byte pointer (which means a byte for the bank followed by a little-endian 16bit address) that points to your custom routine.

Your custom routine should decompress (routines 0x24fd/0x251a do the trick as you might already know) and load (routine 0x009d or 0x00b5, it depends on your needs) the backpic at RAM 0x9310 (starting address of VRAM used to load the second sprite in most situations of the game).

Offline

#10 2012-06-27 18:22:59

Danny-E 33
Administrator
Registered: 2012-06-09
Post 12/1,023

Re: Pokemon Red: Backsprites

Sawakita wrote:

Hello, sorry for not having been around for a while.

Now, regarding the question: The routine that loads the monsters' backpics starts at address 0x3f103.
For those who are interested it's pointed by the fifth (although its ID is 0x04 since arrays are 0-based) 3-byte-pointer of the PredefPointers (in the linked page, you can do a quick Ctrl-F search for "PredefPointers:" to find the table, since the file is large).

Well, that web page was too large and froze up my internet browser.. Luckily, then I realized I've already downloaded that file so I just opened it up in Microsoft Visual C++ and Ctrl+F worked just fine to find the location you're reffering to. Unfortunately, I have a very very minimum knowledge of ASM and I'm unsure what I'm looking at, at"PredefPointers:"... :/
Is line "dbw $0F,$7103" the line you're reffering to as the 5th 3-byte pointer on the "PredefPointers:" table? And $7103 is the pointer while $0F is the bank, because you said this is pointing to the routine at 0x3F103, right?

Sawakita wrote:

What I did for my hack is repointing that routine to another one I wrote (you can get all the code at my pokewood repository; again, you can Ctrl-F "MagnifyBackPic_hacked:", to find the main code). Consider that the code I wrote there is one of my first attempts at ASM coding, and at the time I was even still coding right on the ROM (instead of assembling-linking my code the right way) that's way it's such a spaghetti-mess. Also that specific routine relies on several other hacks I made in that ROM (including arranging pics' bank locations into arrays, unlike the original hardcoded banks).

Anyway my suggestion is that you replace the 5th 3-byte pointer of the previously mentioned table with a 3-byte pointer (which means a byte for the bank followed by a little-endian 16bit address) that points to your custom routine.

Your custom routine should decompress (routines 0x24fd/0x251a do the trick as you might already know) and load (routine 0x009d or 0x00b5, it depends on your needs) the backpic at RAM 0x9310 (starting address of VRAM used to load the second sprite in most situations of the game).

Ok, so I think I'm looking at the right thing, but I am confused with what you are saying I should do from here... If I understand correctly, are you saying that it is of no use to use your custom routine from your pokewood repository because it relies on other routines that you've modified? And that instead I should repoint it to a routine that is alreay in the rom at either address 0x24FD or 0x251A? Which would mean changing the line "dbw $0F,$7103" to "dbw $00,$64FD" or "dbw $00,$651A" right? Also, what is the difference between the two routines at 0x24FD and 0x 251A? Or are you saying I still need to write my own custom routine that is just similar to what those two routines do, but the custom routine should also:

"load (routine 0x009d or 0x00b5, it depends on your needs) the backpic at RAM 0x9310 (starting address of VRAM used to load the second sprite in most situations of the game)." but unfortunately, I do not understand what you are saying there...

Thank you so so much for taking the time to help me out! My hack is making some good progress but this backsprite issue has been a big road block for me! I can't wait to fully understand and figure this out with you help! Thank you!

~Danny-E 33

P.S. If I understand you correctly here:

Sawakita wrote:

Also that specific routine relies on several other hacks I made in that ROM (including arranging pics' bank locations into arrays, unlike the original hardcoded banks).

I also do not use the original hardcoded banks for the sprites either. However, I don't know what 'arranging them into arrays' means. I used to the code provided by stag019 further up in this thread to avoid using the hardcoded banks. Is it possible he told me what you did for avoiding the hardcoded banks as well?
Also, you say:

Sawakita wrote:

Also that specific routine relies on SEVERAL other hacks I made in that ROM

What kinds of routines does this include? Is it worth implimenting them in my hack if you would let me in order to also use your custom routine that you refered to in your pokewood repository for not zooming the backsprites? I'm only curious.


Red Hack: Pokémon Prototype

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

Offline

#11 2012-06-29 14:03:00

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

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

I'm unsure what I'm looking at, at"PredefPointers:"... :/
Is line "dbw $0F,$7103" the line you're reffering to as the 5th 3-byte pointer on the "PredefPointers:" table? And $7103 is the pointer while $0F is the bank, because you said this is pointing to the routine at 0x3F103, right?

It's correct.

Danny-E 33 wrote:

Ok, so I think I'm looking at the right thing, but I am confused with what you are saying I should do from here... If I understand correctly, are you saying that it is of no use to use your custom routine from your pokewood repository because it relies on other routines that you've modified? And that instead I should repoint it to a routine that is alreay in the rom at either address 0x24FD or 0x251A? Which would mean changing the line "dbw $0F,$7103" to "dbw $00,$64FD" or "dbw $00,$651A" right?
Also, what is the difference between the two routines at 0x24FD and 0x 251A? Or are you saying I still need to write my own custom routine that is just similar to what those two routines do,...

Your custom routine should call the routine located at 0x24fd. Routine 0x251a implements the actual compression algorithm while 0x24fd is a sort of interface to access more easily the routine at 0x251a. Before you call 0x24fd you load the bank of the compressed data in register a. After the call you can find your uncompressed data in SRAM starting at 0xA188.

Danny-E 33 wrote:

... but the custom routine should also:

"load (routine 0x009d or 0x00b5, it depends on your needs) the backpic at RAM 0x9310 (starting address of VRAM used to load the second sprite in most situations of the game)." but unfortunately, I do not understand what you are saying there...

Routine 0x00b5 copies a certain a number of bytes (value in register bc) from a source address (register hl) to a destination address(register de). Routine 0x009d is an interface to it and allows you to decide the bank too (value stored in register a), unlike 0x00b5 that reads from the current bank. These routines are handy when you need to copy chunks of data (like sprites) from ROM/WRAM/SRAM to VRAM (Video RAM, where you put stuff to be displayed on the screen).

Danny-E 33 wrote:

Thank you so so much for taking the time to help me out! My hack is making some good progress but this backsprite issue has been a big road block for me! I can't wait to fully understand and figure this out with you help! Thank you!

No problem. If I can give you a suggestion, though, you might have an easier time if you learn some more about assembly and about how the GameBoy works internally, because those concepts are fundamental when you rewrite parts of a game engine.

Danny-E 33 wrote:

I also do not use the original hardcoded banks for the sprites either. However, I don't know what 'arranging them into arrays' means. I used to the code provided by stag019 further up in this thread to avoid using the hardcoded banks. Is it possible he told me what you did for avoiding the hardcoded banks as well?

In my hack the code reads the bank byte from an array of bytes (in pokewood repo you can read the source files for front and back pics). So if for example you want to know what bank contains the backpic of Squirtle you read the 7th byte of that array. The code that handles this task is named "GetMonBackPicBank"

Danny-E 33 wrote:
Sawakita wrote:

Also that specific routine relies on SEVERAL other hacks I made in that ROM

What kinds of routines does this include? Is it worth implimenting them in my hack if you would let me in order to also use your custom routine that you refered to in your pokewood repository for not zooming the backsprites? I'm only curious.

Those routines include support for uncompressed sprites, different data organization (and different order). Also, some standard routines might have been repointed (don't remember exactly, though).
Of course you're free to use anything you might find handy from my coding (I uploaded the whole project on https://bitbucket.org/sawakita/pokewood/src, when I realized I was probably not going to finish it).

Offline

#12 2012-06-29 16:31:54

Danny-E 33
Administrator
Registered: 2012-06-09
Post 19/1,023

Re: Pokemon Red: Backsprites

Sawakita wrote:

Your custom routine should call the routine located at 0x24fd. Routine 0x251a implements the actual compression algorithm while 0x24fd is a sort of interface to access more easily the routine at 0x251a. Before you call 0x24fd you load the bank of the compressed data in register a. After the call you can find your uncompressed data in SRAM starting at 0xA188.

Routine 0x00b5 copies a certain a number of bytes (value in register bc) from a source address (register hl) to a destination address(register de). Routine 0x009d is an interface to it and allows you to decide the bank too (value stored in register a), unlike 0x00b5 that reads from the current bank. These routines are handy when you need to copy chunks of data (like sprites) from ROM/WRAM/SRAM to VRAM (Video RAM, where you put stuff to be displayed on the screen).

So, the very beginning of the new routine I need to write should start off with loading the sprite bank into register a and then it needs to call the routine at 0x24FD and then it needs to load the routine at address 0x009D, right? Is there anything else that new routine needs to have in it?

And after the routine at 0x24FD is called, it automatically accesses the routine at 0x251A, right?

And once the game runs the routines at 0x24FD and 0x251A, the uncomporessed sprite is now at SRAM 0xA188 and it's the routine at 0x009D that moves the sprite to VRAM 0x9310?

Do I need to change the values in register pairs bc, hl, and dc for the routine at 0x009D to perform correctly? And isn't the value for the bank already in register a because of the code that stag019 provided?

Also, that zooming routine at 0x3F103 wouldn't ever be used anymore in the end, right? So can't the new routine be written directly on top of it and then the 5th 3-byte pointer would not need to be repointed?

Also, what asm opcodes are responsible for "calling" other routines?

Is an array basically a table?

And what exactly do you mean when you say "interface"?

Sawakita wrote:

If I can give you a suggestion, though, you might have an easier time if you learn some more about assembly and about how the GameBoy works internally, because those concepts are fundamental when you rewrite parts of a game engine.

Right. I'm workin on it. Slowly but surely, I'm starting to get the hang of basic basic assembly :P

Again, I really really thank you for taking to time to help me understand this and being patient. :) I know I probably just sound dumb with how many questions I'm asking, but I really want to be sure I fully understand. I'm really trying. :)

Also, found a small problem with the solution stag019 explained about the sprite banks. The ghost sprite and the two fossil sprites don't work anymore, probably because it is trying to read the 11th byte of the fossils "base stats". But since those three "frontsprites" don't have base stats, I'm unsure what byte is currently in RAM 0xD0D3 when it tries to read for the bank. Can you think of how to fix this?

~Danny-E 33


Red Hack: Pokémon Prototype

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

Offline

#13 2012-07-01 13:07:04

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

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

So, the very beginning of the new routine I need to write should start off with loading the sprite bank into register a and then it needs to call the routine at 0x24FD and then it needs to load the routine at address 0x009D, right? Is there anything else that new routine needs to have in it?

And after the routine at 0x24FD is called, it automatically accesses the routine at 0x251A, right?

And once the game runs the routines at 0x24FD and 0x251A, the uncomporessed sprite is now at SRAM 0xA188 and it's the routine at 0x009D that moves the sprite to VRAM 0x9310?

It's not that simple. You should check how the routine you're replacing is called (what arguments are passed), where it takes the data it needs from. For example I noticed it gets the ID from RAM [0xcfd9] so my code starts by getting the value stored in [0xcfd9] and copying it into [0xcf91] (this RAM location is accessed by various bank#0 routines, for example to load the corresponding base stats, IIRC).
As I've said hacking a routine is not always straightforward, and explaining it by words is even harder. You'll need to explore and understand the exisisting code and especially the RAM used, which is critical to figure out how to build your own hacked code.

Danny-E 33 wrote:

Do I need to change the values in register pairs bc, hl, and dc for the routine at 0x009D to perform correctly? And isn't the value for the bank already in register a because of the code that stag019 provided?

You do have to load the correct values in the registers. Anyway I was talking about the way to use that routine generally. I don't know what you current code look like.

Danny-E 33 wrote:

Also, that zooming routine at 0x3F103 wouldn't ever be used anymore in the end, right? So can't the new routine be written directly on top of it and then the 5th 3-byte pointer would not need to be repointed?

If you can fit your new code in it, yes. Just don't overwrite other unrelated code/data.

Danny-E 33 wrote:

Also, what asm opcodes are responsible for "calling" other routines?

Is an array basically a table?

And what exactly do you mean when you say "interface"?

0xCD is the opcode for "call". It reads the following 2 bytes as the (little-endian) address of the routine to call. So if you want to call a routine located at 0x36e0 you'd write:

CD E0 36

An array is a sequence of consecutive homogeneous data (in this case, bytes).
Sorry, I used the term interface rather loosely: I mean that it reduces the amount of code you need to write in order to call 0x251a (specifically without 0x24fd you'd need to switch the bank and execute the process of enabling SRAM, used by the decompression algorithm)

Danny-E 33 wrote:

I know I probably just sound dumb with how many questions I'm asking, but I really want to be sure I fully understand. I'm really trying. :)

Not dumb at all: you're showing a great will to learn, for what I've seen so far.

Danny-E 33 wrote:

Also, found a small problem with the solution stag019 explained about the sprite banks. The ghost sprite and the two fossil sprites don't work anymore, probably because it is trying to read the 11th byte of the fossils "base stats". But since those three "frontsprites" don't have base stats, I'm unsure what byte is currently in RAM 0xD0D3 when it tries to read for the bank. Can you think of how to fix this?

~Danny-E 33

Those are special cases and should be treated as such: you have to check for those IDs too and pass the correct banks accordingly (which by the way is what the original code does). From iimarckus's disassembly:

; define (by index number) the bank that a pokemon's image is in
; index = Mew, bank 1
; index = Kabutops fossil, bank $B
    ld a,[$CF91] ; XXX name for this ram location
    ld b,a
    cp $15
    ld a,$01
    jr z,.GotBank\@
    ld a,b
    cp $B6
    ld a,$0B
    jr z,.GotBank\@
    ...
.GotBank\@
    jp $24FD

I don't remember where the exact pointers for fossil and ghost are located.

Last edited by Sawakita (2012-07-01 13:11:39)

Offline

#14 2012-07-02 08:25:53

Danny-E 33
Administrator
Registered: 2012-06-09
Post 25/1,023

Re: Pokemon Red: Backsprites

Wow. I guess I just have to get really comftorble with asm before I can understand any further... :/ I'm still trying, but the fundamental concepts of asm are taking a long time to fully wrap my mind around. And even then, I don't know how I'm supposed to get very comftorble with the asm engine of the rom itself... I guess, do you have any advice for me?
I suppose I don't see much of a point in asking a bunch more questions until I'm able to understand the answer to the questions. So for now I'm just gonna dedicate my time to learning asm concepts inside and out. Do you have any suggestions how/where I can learn more asm outside of ASM School?
Thanks :)


Red Hack: Pokémon Prototype

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

Offline

#15 2012-07-02 20:21:11

Tauwasser
Member
Registered: 2010-10-16
Post 287/447

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

asm engine of the rom itself...

Huh? That's not an "engine", that's the GB's CPU! It's the basic instruction set used by all games on all Gameboys! It's not being interpreted or emulated, it's directly what the CPU reads and executes!

cYa,

Tauwasser

Offline

#16 2012-07-03 05:08:49

Danny-E 33
Administrator
Registered: 2012-06-09
Post 26/1,023

Re: Pokemon Red: Backsprites

Oh, I guess my vocabulary is not quite accurate... I mean that even once I become comftorble with what asm is and what it can do, I still don't know how I'm supposed to get comftorble with the many routines specific to Pokemon Red, and with interpreting what each routine I'm reading means. And therefore, understanding how to know what modifications I need to make to which routines for the result that I want.

Even once I learn the concepts of asm, I don't know how to understand how Pokemon Red applies those concepts.

Does that make more sense now?


Red Hack: Pokémon Prototype

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

Offline

#17 2012-07-03 13:15:58

Miksy91
Member
Registered: 2010-10-16
Post 945/2,308

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

Oh, I guess my vocabulary is not quite accurate... I mean that even once I become comftorble with what asm is and what it can do, I still don't know how I'm supposed to get comftorble with the many routines specific to Pokemon Red, and with interpreting what each routine I'm reading means. And therefore, understanding how to know what modifications I need to make to which routines for the result that I want.

Even once I learn the concepts of asm, I don't know how to understand how Pokemon Red applies those concepts.

Does that make more sense now?

The thing is that no one else can do any better than you do. The way to understand it would be by taking a look at what calls to rom bank 0 do and which ram offsets are used in which kinds of "scripts" etc. Once you've it all documented, it's much easier to take a look at existing codes you haven't yet.

Last edited by Miksy91 (2012-07-03 13:16:23)

Offline

#18 2012-07-04 02:40:31

Danny-E 33
Administrator
Registered: 2012-06-09
Post 30/1,023

Re: Pokemon Red: Backsprites

Miksy91 wrote:

The way to understand it would be by taking a look at what calls to rom bank 0

What exactly do you mean by this? How exactly do I "take a look" at what calls to rom bank 0? And what do I do with that information? I don't really know what I'm asking, so I'm sorry if these questions seem elementary.. :P


Red Hack: Pokémon Prototype

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

Offline

#19 2012-07-04 04:55:27

Miksy91
Member
Registered: 2010-10-16
Post 947/2,308

Re: Pokemon Red: Backsprites

For example in GSC, I've learned by experience that by calling $0F5E, font is loaded and text in hl is shown.
*I'm not actually even sure if it goes this way or not but I believe it does.

Then there is YES/NO box asm call command, not remember what it was but I'll write them down in my pc as they might come in handy (although both can be done easily through a script). Anyway, I actually meant that by looking through some of the existing assembly routines by knowing what they do, you can assume what different call commands do - especially if you "nop" them away.

Offline

#20 2012-07-04 14:26:39

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

Re: Pokemon Red: Backsprites

The most effective way to learn GB ASM, in my opinion, is to see how the code flows, using a debugger (BGB is good for this). That's how I learned, at least (well, after reading some basics about z80 registers, pointers and understanding the Game Boy memory mapping).

In my case, the first thing I wanted to accomplish was to understand how the decompression algorithm worked, so I put a breakpoint at that routine's entry point (found the address in a forum's post, somewhere) and started following the code, with its jumps, loops, etc.

As far as routines' addresses are concerned you're much luckier than I was; when I started I could barely find a handful of routines explained around the internet. The disassembly has now tons of disassembled code so you can check the location of a certain routine easier (labels and comments help in that sense). Really, the disassembly is your best friend in this situation. Also, I released my notes about the usage of certain routines that I found interesting (you can get check these notes at the disassembly wiki). They're mainly related to map events, but there are also several general-purpose routines.

You can run the code step-by-step by pressing F7, F8 skips the current routine, F9 returns to runtime mode; anyway I noticed that each time I tried to explain how one goes about debugging with BGB I couldn't get people to understand me, so I believe the best way to learn it is to try by yourself, by applying the classical trial-and-error process. If you're missing a particular BGB command or syntax (e.g. for setting an on-access breakpoint), feel free to ask, it's easier to anwer a question like that than explaining how the whole debugging process works.

Last edited by Sawakita (2012-07-04 14:33:52)

Offline

#21 2012-07-04 19:37:56

Danny-E 33
Administrator
Registered: 2012-06-09
Post 32/1,023

Re: Pokemon Red: Backsprites

I'll definitely take a deeper look at the disassembly and learn to use bgb as a debugger.
I also feel like making a routine to simply not zoom the backsprites shouldn't be this complex... I would think that the routine that performs the nearest-neighbor interpolation could just be rewritten to mimic how the frontsprites are loaded. The only differenes would be ram locations and the coordinates on the screen.. Is it necessary for there to be so many steps? I might have a better time understanding if I knew the process of loading a frontsprite normally.


Red Hack: Pokémon Prototype

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

Offline

#22 2012-07-05 14:05:03

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

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

I'll definitely take a deeper look at the disassembly and learn to use bgb as a debugger.
I also feel like making a routine to simply not zoom the backsprites shouldn't be this complex... I would think that the routine that performs the nearest-neighbor interpolation could just be rewritten to mimic how the frontsprites are loaded. The only differenes would be ram locations and the coordinates on the screen.. Is it necessary for there to be so many steps? I might have a better time understanding if I knew the process of loading a frontsprite normally.

It's easy indeed. You just need to decompress the sprite (the decompression algorithm uses the SRAM as a support memory to decompress the data) and then copy the decompressed image in the VRAM.

The problem is that without context there's no way you can incept this simple code into a pre-existing game (without breaking anything else). You have to know where in SRAM the sprite is decompressed (it's at 0xA188, for your information), where in VRAM the backsprite is normally loaded (it's at 0x9310), what the process to read/write SRAM and VRAM is, how much bytes is the decompressed data large, what  the replacement of the "zooming" routine implies (so that you're not missing anything when you replace it), how smaller sprites (i.e. sprites smaller than 56x56 px) are centered before being copied into VRAM, where the various IDs, sprite pointers, are stored in memory so that you know where to get them, etc..

Offline

#23 2012-07-06 02:43:47

Danny-E 33
Administrator
Registered: 2012-06-09
Post 35/1,023

Re: Pokemon Red: Backsprites

Wow.. To be honest, alot of this is very discouraging... I feel like I'm not gonna be able to understand all of this and get to the answer unless I am spoon-fed what to do... And I don't like the idea of having the answer just handed to me without me figuring some of it out for myself... :/


Red Hack: Pokémon Prototype

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

Offline

#24 2012-07-06 04:02:17

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

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

Wow.. To be honest, alot of this is very discouraging... I feel like I'm not gonna be able to understand all of this and get to the answer

Don't get too discouraged, it'll take time but you'll get it.

Danny-E 33 wrote:

unless I am spoon-fed what to do... And I don't like the idea of having the answer just handed to me without me figuring some of it out for myself... :/

At least you're going about this the right way.


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

Offline

#25 2012-07-06 04:59:17

koolboyman
Member
Registered: 2010-10-16
Post 68/203

Re: Pokemon Red: Backsprites

Danny-E 33 wrote:

And I don't like the idea of having the answer just handed to me without me figuring some of it out for myself... :/

THAT'S the kind of attitude I like to see.  Keep trying.

Offline

Board footer

Powered by FluxBB