User talk:Shiny

From Data Crystal
Revision as of 17:52, 8 December 2014 by Shiny (talk | contribs) (→‎Sprite animation data)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Sprite animation data

Hello! Sorry to bother you again, but I have more to mention about sprites. I noticed recently that you added this useful animation information here. I played around with this a bit and I was able to understand what you wrote there, which really helps with my understanding of sprites.

While your information explains the necessary tiles to use (including the pointers) and their positioning -- all for each animation frame -- I found data that determines where this animation ID is found in the first place, as well as the animation cycle, which seems to determine things like how the animation should loop and the duration of an animation frame, among other things.

To begin, there's a four-byte structure that determines the sprite appearance and behavior from 0x7C001-7C160. (All of the offsets that I mention apply to both the GB and GBC versions of DKL3 unless stated otherwise.) The four-byte structure that is used depends on the value in HRAM address FFD7 in the English version of DKL3 (or FFD6 in the Japanese version). This byte here is related to the most recent sprite loaded in RAM. I'll use the DK Barrel as an example since it's one of the first things you see in the game. When the DK Barrel is the most recent sprite loaded in RAM, this byte has the value of 0D, and this four-byte structure can be found starting at 0x7C001 + 0D * 04 = 7C035, and it ends at 7C038.

The data here is 02 0C 0C 00. I'm not sure what the first byte does -- it's always 01 or 02. The second byte, 0C in this case, determines which sprite to use (its appearance), which I'll explain in detail below. The third byte, also 0C in this case, seems to determine the sprite's behavior (for example, this is what makes the DK Barrel give you a second Kong if you only have one). The fourth byte always seems to be 00 and I haven't found its purpose.

I've focused most on the second byte at offset 0x7C036, so I'll explain how that works. This serves as an index to the pointer table located at 0xC001. Not surprisingly, this is a 3-byte pointer, where the first byte is the ROM bank and the next two bytes are a big-endian pointer. (Rare sure does love to use big endian pointers, which is kind of odd for a Game Boy game...) Each pointer serves as a branch destination. Given the index 0x0C, this means that our pointer is at 0xC025. The data here is 03 47 CE, which is a pointer to 0xC7CE. This means that the code will jump to here upon loading a DK Barrel.

The code for the sprite handling has a few things in common for all sprites. The pointer for the sprite animation data is loaded into bc, then it jumps to 3:73AC (or F3AC when viewed in a hex editor) to write this pointer to RAM. Also, I don't know what type of syntax you're used to -- this syntax is what BGB uses by default, which is what I'm accustomed to.

                                         ;Data for current sprites on screen starts at C100 in RAM,
ROM3:47CE 62               ld   h,d      ;with a 32-byte structure for each sprite.
ROM3:47CF 6B               ld   l,e      ;de = C100, C120, C140, etc. depending on the sprite.
ROM3:47D0 01 07 48         ld   bc,4807  ;3:4807 is where the DK Barrel's animation cycle is located
ROM3:47D3 C3 AC 73         jp   73AC     ;All of these sprite animation routines jump to 73AC

ROM3:73AC 7D               ld   a,l      ;Write the big-endian pointer (from bc, determined above) to 
ROM3:73AD E6 E0            and  a,E0     ;(C11A), (C13A), (C15A), etc., which will be read from later.
ROM3:73AF C6 1A            add  a,1A
ROM3:73B1 6F               ld   l,a
ROM3:73B2 70               ld   (hl),b
ROM3:73B3 2C               inc  l
ROM3:73B4 71               ld   (hl),c
ROM3:73B5 2C               inc  l
ROM3:73B6 AF               xor  a        ;Write the byte 00 to (C11C), (C13C), (C15C), etc.
ROM3:73B7 77               ld   (hl),a
ROM3:73B8 C9               ret

Here is the data at from 0xC807 to 0xC813:

81 71 03 07 0B 0F 13 17 1B 1F 80 48 09

I haven't figured out exactly how this data works, but the relevant code for this is at 0x1ABF in the GBC version. There are a lot of branch cases from 0x1AC8 to 0x1B22 depending on what byte is being read (again, these offsets are for the GBC version). One thing I did figure out, though, is that when 0x81 is being read (which is at the very beginning here), the byte afterwards determines the animation ID. I also know that the 48 09 byte sequence at the end is a pointer to loop back to C809, but that's all that I know about that so far.

I'm almost done here, but I'd also like to being up one other sprite -- Bear. You may or may not know that Bear's sprite is animated in the GB version, but it was messed up in the GBC version and only displays the first frame. So, I'll explain how to fix it!

Let's go back to offset 0x7C036 and change this from 0D (DK Barrel) to 47 (Bear). The new jump pointer is therefore at 0xC0D6. This byte sequence is 03 68 13, which makes the branch pointer 0xE813. The code is below -- it's a bit longer and I'm not 100% sure what the additional code does, but there's still the jump to 73AC as well as the pointer that is loaded to bc.

                                         ;Data for current sprites on screen starts at C100 in RAM.
ROM3:6813 62               ld   h,d      ;de = C100, C120, C140, etc. depending on the sprite.
ROM3:6814 7B               ld   a,e      ;
ROM3:6815 C6 0D            add  a,0D     ;Write byte 00 to (C10D), (C12D), (C14D), etc. (not sure 
ROM3:6817 6F               ld   l,a      ;yet what this does)
ROM3:6818 3E 00            ld   a,00
ROM3:681A 77               ld   (hl),a
ROM3:681B 7B               ld   a,e
ROM3:681C C6 16            add  a,16     ;Reset bits 0 and 1 of (C116), (C136), (C156), etc.
ROM3:681E 6F               ld   l,a      ;(Not sure what this byte does either)
ROM3:681F CB 86            res  0,(hl)
ROM3:6821 CB 8E            res  1,(hl)
ROM3:6823 01 29 68         ld   bc,6829  ;3:6829 is where Bear's animation cycle is located
ROM3:6826 C3 AC 73         jp   73AC     ;All of these sprite animation routines jump to 73AC

Now here's the interesting (but not too surprising) part: This data differs between the GB and GBC versions! It starts at offset 0xE829.

Here's the byte sequence in the GB version:

81 45 82 00 00 84 08 03 07 0B 0F 13 0F 0B 07 83 68 30 84 03 00 04 08 0C 10 0C 08 04 83 68 3D 80 68 2E

And here it is in the GBC version:

81 45 82 00 00 00 95 84 08 03 07 0B 0F 13 0F 0B 07 83 68 32 84 03 00 04 08 0C 10 0C 08 04 83 68 3F 80 68 30

The GBC version has two extra bytes 00 95, which aren't present in the GB version. I removed these bytes (and adjusted some pointers that came afterwards by subtracting these by 2) and this fixed the animation. You can see this fix in this English patch that I made some time ago. (I'm not sure what the 00 95 actually does, but it clearly doesn't belong there.)

Also, as before, you can see the byte 45 at offset E82A, which is Bear's animation ID. This is consistent with what you mentioned here a while ago.

I hope this explanation isn't too long or complicated, but I needed to explain a lot of detail here. I realize I can get quite wordy with things... If you have any questions about this, let me know! --Blaziken257 21:19, 7 December 2014 (EST)

That's an interesting (and detailed!) explanation.
So the data I had found wasn't actually animation data and would be more accurately described as metasprite definitions. It's sad to see that the pointers to the real animation data are hard-coded and don't appear to be organized in a table where they could be easily extracted.
I had actually found the table you refer to at 0x7C001 before, but didn't inspect it in as much detail because it seemed to point mostly to data for object initialization callbacks. I had no idea that the secret to finding the real animation data was hidden in those callbacks.
--Shiny (talk) 12:52, 8 December 2014 (EST)