Author Topic: Fun with Summons  (Read 6837 times)

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Fun with Summons
« on: October 08, 2013, 10:14:14 PM »
I'm going to post the full how-to on this thread for ease of understanding (instead of making you read back through multiple posts in the Summons and Graphics topics), but It'll take a while to write the darn thing because the processes are a bit complicated to explain (though, once you get the hang of it, not so hard to do).

So what you have here is an ips patch and a save file.
 :edit: Save file link is broken, and I do not currently have a backup. I will restore this at some point. Sorry for the inconvenience. IPS file still works, though, but you'll have to hack in an appropriate save state.
Apply the ips to a clean FF2US v1.1 ROM and rename it to match the save file. Load the saved game (don't start a new game - I cannibalized some of the basic enemy fight routines and accidentally made it so Cecil's maid never moves away from the hallway she's blocking).
You'll start in the Baron region with Cecil, Kain and young Rydia. They all have better than normal starting levels and equipment, and Rydia has "Shadw" in her Summon list. This is a fully-working Shadow Dragon summon. It costs 99 MP and destroys one enemy 100% of the time. It replaces Imp.

Try it out. Walk around and get into a fight. You'll notice that Baron is populated with some new enemies: namely, Shiva, Indra and Jinn. Each of them will change their spriting, cast the "1" spell of their respective element, then change back.

Obviously, the purpose of this little hack is to demonstrate the applications of what I've discovered about changing "special" monster images and changing summoned monsters. I'll be posting the step-by-step how-to for all of this here over the coming week or so.
« Last Edit: February 17, 2015, 10:38:03 AM by chillyfeez »

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Re: Fun with Summons
« Reply #1 on: October 08, 2013, 10:32:29 PM »
Now that was cool. And things like this will represent the future of large scale FFIV Hacking. That you even managed to include the sprite shifting is quite impressive and I am so glad to see that you figured out the issue with Summoning! Keep up the incredible work!

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #2 on: October 09, 2013, 09:30:43 PM »
I'll focus first on how I changed Imp, Eagle and FloatEye into Jinn, Indra and Shiva. This is, by far, the easier of the two modifications in this hack, and some of what is done here will be referenced (mostly as a point of contrast) when explaining how to change summon images.

The first thing to note is that these three summons - three of the only five that never appear as enemies in the original programming - are irregular sizes. In an early hacking experiment, I used Tile Layer to copy Jinn's sprites over those of an existing monster, including the empty spaces necessary to make the image fit properly in a rectangular area. This worked fine, but there were a few problems/limitations to employing this method. First - doing so meant erasing the image data of an existing monster (I used EvilMask). This could have been avoided by using one of the large banks of empty data at 6EA20 or 68448, but these banks become very valuable when altering summon images, whose pointers present far more limitations than those of enemy monsters. The second problem with this method is that it does not allow for image changing. Enemies can only change size/shape if the target size/shape is one of the "special" sizes (Size byte is 80 or higher). So, in order to undertake a project like this, I decided to learn the previously undocumented information about the Special sizes.
Turns out it all starts in a table at 7D000. Each Special size (numbered 80-BF) has a five-byte entry in this table. I still don't know absolutely everything each of these bytes does, but I learned enough for what I wanted to do:
Byte 0: x-position (Special sizes have a fixed x/y that ignores battle arrangement), plus other unknowns
Byte 1:
 bits 0-5: points to to a location in the size table at 7015E
 bits 6-7: unknown
Byte 2: Palette (Special sizes ignore the standard monster palette byte - This is how K. Eblan and Q. Eblan change palettes mid-battle)
Byte 3: unknown
Byte 4: indicates which pointer to use for sprite arrangement data (more on this later)

So, D. Mist's initial form (size 80) reads:
35 91 A1 02 00

35 - small changes to this byte will move D. Mist forward or backward. Large changes do more drastic (and seemingly erratic) things.

91 - bits 0-5 point to the monster's rectangular size, so break 91 into its bits: 10010001, then disregard bits 6-7: 010001, and you get 11. So we're using size 11 on the table at 7015E. Each of these sizes is two bytes (x and y sizes) so start at 7015E (00) and count up two bytes at a time until you get to size 11, which is 0A 08. So D. Mist is 10 bytes wide and 8 bytes tall. If we wanted D. Mist to be 2x2 instead (size 00), we would change bits 0-5 to 0 (but keep bits 6-7 the same), so we would change this byte to 80.

A1 - D. Mist uses monster palette A1.

02 - unknown

00 - D. Mist uses the first tile arrangement pointer.

Now, let's take a look at the tile arrangement...
The tile arrangement pointer table is located at 75100. Each pointer is two bytes. reverse the order and add the value to 68200 to find the tile arrangement for the size in question. So, D. Mist uses the first pointer, 72 CF.
CF72 + 68200 = 75172. This is the address of D. Mist's tile arrangement data.
When the game starts loading a monster image, it firsts loads some crazy amount of sprites into memory. Presumably, this is necessary in order to load Zeromus, but for all other monsters seems like a waste. The sprite arrangement is a sequence of bytes that either indicate empty space, or which - of the sprites that have been loaded - to display. The arrangement does not need to tell the game when to move to the next line, because there is a predetermined rectangular space to work within. For the same reason, you don't need to tell the game where to stop. Within the sprite arrangement, 00-FD each represent a sprite (in the order they appear). FF represents a single empty space. FE XX represents multiple empty spaces, where XX is the amount of empty spaces.

D. Mist's tile arrangement reads:
Code: [Select]
-- -- FE 06 00 01 02 FE 06 03 04 05 06 FE 03 07
08 09 0A 0B 0C 0D FE 03 0E 0F 10 11 12 FF 14 FE
03 15 16 17 18 19 FE 05 13 1A 1B 1C 1D 1E 1F FE
02 20 21 21 22 23 24 25 26 FF 27 2F 2A 2B 29 2A
2B 2C 2D 2E

Keeping in mind that D. Mist is 10x8, this means that the arrangement will end up looking like:
(where an X is a sprite and a - is an empty space)
Code: [Select]
------XXX-
-----XXXX-
--XXXXXXX-
--XXXXX-X-
--XXXXX---
--XXXXXXX-
-XXXXXXXX-
XXXXXXXXXX

So, that's how it works. In the next post (maybe tomorrow), I'll demonstrate how this system was harnessed to transform an enemy monster into Jinn.

 :edit: sorry - this all is just a re-telling of info I've already posted, but it's presented in a much more clean fashion, and serves as a necessary basis for what will follow.
« Last Edit: October 09, 2013, 10:13:26 PM by chillyfeez »

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #3 on: October 11, 2013, 11:29:10 AM »
So, now that we know how Special sizes work, time to make them work for us.
Here is how I turned Imp into Jinn...

Imp has the first entry in the enemy graphic properties table at 7CC00.
By default, Imp's data reads:
01 00 03 C1

First thing we want to focus on is the last two bytes, the graphical pointer.
Imp's Graphical pointer is 03 C1, or C103. The formula to use is ([pointer] * 8) + 8200 = Beginning of graphical data.
so
C103 * 8 + 8200 = 60818 + 8200 = 68A18 This is the beginning of Imp's graphic
Jinn's graphic starts at 69E40 (found by using Tile Layer)
so
69E40 - 8200 = 61C40
61C40 / 8 = C388 This is Jinn's Graphic pointer (written as 88 C3)

So now we have 01 00 88 C3

As previously stated, The palette (second byte) means nothing when employing a Special size, so we can ignore that entirely.

The next (recommended) step is to use Tile Layer to lay out Jinn's sprites. This will serve two purposes:
1) we will know how large of a rectangular area we need to use
2) we will be better able to visualize what we need to do with sprite arrangement
So, doing this, we see that Jinn requires an 8x6 rectangle.
(Keep Tile Layer open in the background. We'll be referring back to this arrangement later.)
It's recommended to use a Special size that is already 8x6 or larger. While we can customize the size of the rectangle easily, we have a finite amount of data to work with for sprite arrangement (unless we change the pointer to change the location of the sprite arrangement data - which is possible, but more trouble than it's worth). For this hack, I decided to use D. Mist's size (80; also 81, but more on that later).

We know the details for Special size 80 are at 7D000, and are 35 91 A1 02 00.
First thing to do is to change to the right palette (third byte).
I want to be sure Jinn uses the correct palette. Summoned monsters' palette assignments are located at 7004C. Count along this list until we get to the 8th byte (Jinn is the 8th summon): D0. This is what we will set for the third byte of our special size details. so now we have:
35 91 D0 02 00

We could change the 5th byte in order to assign a different set of sprite arrangement data, but again, more trouble than it's probably worth. We'll keep that at 00.

The last thing to do here is to change the size assignment. As previously detailed, this Special size uses the 11th (hex) size in the size table, 0A 08. This is a bigger rectangle than we need. Two options here: either change 0A 08 to 08 06, or point to a different location in the size table. The latter is the wiser idea, because this will leave 0A 08 available for other monsters' needs. Because this was my first try at it and I didn't know everything yet, I chose the first option. I used the second (wiser) option for Indra and Shiva. I'll go into that a bit when this is over.

So now we have the right size, palette and sprites for Jinn. Last thing (sorta) to do is to create the right sprite arrangement. So, as noted in the previous post, size 80 uses the first sprite arrangement pointer 72 CF. We add CF72 to 68200 to get to the location of the sprite arrangement data: 75172.
Remember we left Tile Layer open with our arranged sprites? Bring it back up. It's a good idea to have Tile Layer and your Hex editor up side-by-side for this. The good news is, unlike D. Mist, Jinn's sprites all appear in the proper order, so when we don't have blank spaces, we can just count up. This is mostly true for Indra and Shiva, too, but not entirely. I'll explain what I mean by that in a later post.
We could, to make things easier, open up a notepad to make this whole process a bit easier to visualize. We know from our arrangement in Tile Layer that Jinn needs to look like this:
Code: [Select]
--XXXXX-
-XXXXXXX
-XXXXXXX
-XXXXXXX
XXXXXXXX
XXXXXXX-
So in order to make the arranging easy in my hex editor, I typed that out without any line breaks:
Code: [Select]
--XXXXX--XXXXXXX-XXXXXXX-XXXXXXXXXXXXXXXXXXXXXX-For me, this saved me a bit of thinking when writing the arrangement data. Anyway, whether you need to use that step or not, the end result will look like:
Code: [Select]
-- -- FE 02 00 01 02 03-04 FE 02 05 06 07 08 09
0A 0B FF 0C 0D 0E 0F 10-11 12 FF 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F-20 21 22 23 24 25 26 27
28 FF
D. Mist's original arrangement will continue for a bit after this, but you don't have to worry about that. You've programmed in 48 sprites and spaces to fill your 8x6, so the game will stop looking after that.

So now we have a fully altered monster - Imp looks like Jinn. But why stop there? The GFX team went through the trouble of programming in two beautiful images for each of the three elemental summons, but we only get to see them for very brief periods at a time. Furthermore, Special-sized enemies can change their image mid-battle - so let's do it!

Most of this process will be the same as above, so I'll try to be brief.

We're going to use D. Mist's "Mist" form for this one (we've already used one formation, so we might as well use its partner). That's Special size 81 (I documented these all here, by the way), which is at 7D005 and reads:
05 9E A1 02 01

The second form will always use the same palette as the first for summoned monsters (summons load only one palette), so we'll change A1 to D0.

We're going to make a change to the first byte here. Notice that for size 80, it's 35, but for size 81 it's 05. If we keep it this way, Jinn will move backwards a bit when he changes shape. So change the 05 to 35 and this won't happen.

Now, here's where my novice was showing again. The second byte, 9E, refers to a different size than that of Size 80. The wise thing to do would be to make this value the same as before, as the second form of Jinn is also 8x6. I didn't do that - I changed THIS size to 08 06 (from 11 08). Fine for this hack, which doesn't allow the player to see more than a few monsters, but for larger scale operations, change the second byte from 9E to 86 to use the already existing 8x6.
So now at 7D005 you'll have:
35 86 D0 02 01

We're done making changes here. On to arranging Jinn #2's sprites.
Size 81 uses the second sprite arrangement pointer, which is at 75102 and reads B4 CF.
Add CFB4 to 68200 to get 751B4. This is where we will start our sprite arrangement.
Same prep process as before, but remember - we're using the SAME bunch of sprites that were loaded for Jinn's first image. Since none of them are repeats from before (which is in contrast to what happens with Shiva and Indra), the first sprite in this arrangement will be the one after the last sprite from the previous arrangement.
In other words, Jinn #1 ended at 28, so Jinn #2 will begin at 29.
The end result will be:
Code: [Select]
-- -- -- -- FE 02 29 2A-2B 2C 2D FE 03 2E 2F 30
31 32 33 34 35 36 37 38-39 3A 3B 3C 3D 3E 3F 40
41 42 43 44 45 46 47 48-49 4A 4B 4C 4D 4E 4F 50
51 52 53

So now we've "drawn" Jinn #2. Only thing left is to change the AI so that Jinn #1 changes into Jinn #2.
Remember I said that only Special-sized monsters can change shape? Well that bit of info provides a key here. You'll notice that when a monster changes image (as originally programmed), the game says (translated into plain English) "Change sprite to 01," or whatever. Well, since Special sizes start at 80, add 80 to this command to know which Special size you are changing to (or contrapositively, subtract 80 from your Special size to know how to script the transition).
So, to make Jinn turn into form #2, "Change sprite to 01."
To make him change back to form #1, "Change sprite to 00."
(If you wanted to make Jinn change to Special size A7, "Change sprite to 27," or "39" in base 10)
I'm assuming, by the way, that you're using Ff4kster to rewrite AI. If you're reading this and you are serious about hacking FF2US and you've never used Ff4kster... well... Get Ff4kster.
I chose to chain together the form change and the attack spell. My original plan was to chain "Form change-attack spell-revert" all together, but it seems that if the last part of the chain is not an attack, then the attacks in the chain will not cause damage. Weird. So instead I increased the monster's speed and made the revert its next action.

So that's it for today. Next up is the marginally different process for Shiva and Indra. It will be a significantly shorter post. Then we'll get into changing Summoned monsters' images, which is enormously complicated to explain and will probably be the longest tutorial in this thread.

 :edit: Sorry it's taken me so long to follow up. Real life's been a bit busy, and in the off time I became semi-obsessed (again) with a hacking experiment that's not really going as well as I'd hoped. I'll finish the Special sizes tutorial tonight or tomorrow, then will get into summoned monster images very soon. Promise.
« Last Edit: October 16, 2013, 09:17:46 AM by chillyfeez »

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #4 on: October 17, 2013, 05:22:16 PM »
Ok, this post will contain the slightly different steps taken to transform Eagle and FloatEye into Indra and Shiva.
I won't explain everything step-by-step. I'm assuming you've read the Imp --> Jinn post, and most of the process is the same.

Eagle uses the third entry in the Graphical data bank at 7CC00, which is
03 02 63 C1

We're turning Eagle into Indra, so first we use Tile Layer and our Hex calculator to figure out Indra's sprite pointer is C2EC, and now we have
03 02 EC C2

Shiva and Indra both require a 6x6 area to work within. This is good, because most Special sizes are larger than 6x6, so it doesn't matter too much whose data we take over. I chose Valvalis, only because I wanted to use monsters that normally undergo image transformations for my first stab at this. Valvalis's initial form is Special size 95. Now we have
95 02 EC C2
And we're done here.

Now to edit special size 95...
Start at 7D000 and count up by fives until you get to the 16th entry, at 7D069.
Note: a quick and easy way to find the appropriate entry is to look at the last byte of each. They are numbered in order beginning at 00 up through special size 9C.
The details for Special size 95 read:
35 18 B1 02 15
Byte 00 (35): Stays the same, unless you want to move Indra forward or backward
Byte 01 (18): Indicates the actual size entry. We want 6x6, which is size 04.
Byte 02 (B1): The palette - Indra uses palette CF
Byte 03 (02): Don't know what it does. Best not to mess with it.
Byte 04 (15): Indicates sprite arrangement. You can, and probably should, keep this the same. When I was at this point, I still did not fully understand what I was doing, so I started writing Indra over K. Eblan (size 9D). I thought I hit a roadblock when I discovered that both of K. Eblan's forms use the same sprite arrangement. Now I know that this is untrue, but it caused me to do something a little weird here. Because I had already arranged Indra over K. Eblan by the time I switched to using Valvalis, I kept K. Eblan's Sprite arrangement. So I changed this byte to 1E. If you're following this easily enough, you don't have to do that, but for the sake of demonstration I'll stick to describing exactly what I did here, exactly as I did it.
So now at 7D069 we have:
35 04 CF 02 1E

On to sprite arranging.
We are looking at the 1Eth sprite arrangement pointer in the index at 75100. Start at 00 and count up two bytes at a time to get to 7513C: BC D8
Add D8BC to 68200 to get 75ABC. This is the location of our sprite arrangement data.

Indra looks like this:
Code: [Select]
--XX--
XXXXX-
XXXXXX
XXXXXX
XXXXX-
XXXXXX
or:
Code: [Select]
--XX--XXXXX-XXXXXXXXXXXXXXXXX-XXXXXXAnd as with Jinn, these sprites all appear in order, so our arrangement data will look like this:
Code: [Select]
-- -- -- -- -- -- -- ----- -- -- -- FE 02 00 01
FE 02 02 03 04 05 06 FF-07 08 09 0A 0B 0C 0D 0E
0F 10 11 12 13 14 15 16-17 FF 18 19 1A 1B 1C 1D

That's it for Indra #1. Now for Indra #2...
We'll be writing over the details for Valvalis #2 now, at 7D06E:
35 18 B1 02 16
changes to
35 04 CF 02 02
All the same reasoning as above. Oops! looks like I was still wasting time messing with byte 04 here. So while we wrote over Valvalis #2's details here, we'll be writing over Titan #1's sprite arrangement. Ah well...
Sprite arrangement pointer 02 is 08 D0... Nope! look at this, I changed that, too. I was still learning, I guess. Looks like what I did here was point to just beyond the last bunch of arrangement data. My pointer 02 reads 60 DF.
68200 + DF60 = 76160
By default, this is a bank of ten lines of FFs. My custom Indra #2's sprite arrangement starts here. Sorry if this is a bit confusing, but at least it does show off some of the freedoms you have in this process.

The most notable thing about Indra #2 (in contrast to Jinn #2) is that some of the sprites from the first form are re-used. Notice, looking at Tile Layer, that Indra #2 doesn't have any feet. This is because between the two images, the bottom two rows of sprites are the same. This is something to keep in mind when planning your arrangement.
Indra #2 will look like this (Where "-" is empty space, "X" is a previously unused sprite, and "O" is a repeated sprite):
Code: [Select]
--XXXX
XXXXXX
XXXXXX
XXXXXX
OOOOO-
OOOOOO
or
Code: [Select]
--XXXXXXXXXXXXXXXXXXXXXXOOOOO-OOOOOOBe sure the sprites used in place of those Os are the same sprites used in the first image.
You'll end up with:
Code: [Select]
FE 02 1E 1F 20 21 22 23-24 25 26 27 28 29 2A 2B
2C 2D 2E 2F 30 31 32 33-13 14 15 16 17 FF 18 19
1A 1B 1C 1D

The only thing left now is to Edit the monster's AI. Whereas with Jinn (which used sizes 80 and 81), you first changed sprite to 1, then reverted to 0; for Indra you'll change sprite to 22 (that's 16 hex in base-10), then revert back to 21.

So there's Indra. I'm gonna go right into Shiva now, which should also be a demonstration of how, by the third time, I knew how to do this without any wasted steps...


chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #5 on: October 17, 2013, 08:28:40 PM »
This should be the shortest one yet - by the time I turned FloatEye into Shiva, I was able to do the whole thing from scratch in under 30 minutes. Hopefully this translates into being able to explain it quicker, too.

Alright, FloatEye's Graphical data is at 7CC0C and reads:
04 03 50 84
Shiva's sprites start at 694F8, and we'll be taking over Kainazzo's data, so we'll change this to:
92 03 5F C2

Now we change Special size 92's details at 7D05A from:
38 95 AA 02 12
to:
38 84 CE 02 12
Yessss. I finally figured out by this point that the only things I needed to change here were the size (bits 0-5 of Byte 01 changed from 15 to 4, to result in 84) and the Palette (Byte 02 from AA to CE).

While we're here, let's change Special size 93 so It's ready for Shiva #2. It's the next five Bytes, beginning at 7D05F.
Was:
38 96 AA 02 13
Now:
38 84 CE 02 13

And now it's time for sprite arranging.
Special size 92 uses the 12th (hex) pointer at 75100, so that's at 75124 and reads 79 D5.
D579 + 68200 = 75779

Shiva #1 looks like:
Code: [Select]
-XXX--
XXXX--
XXXXX-
XXXXX-
XXXXX-
XXXXX-
or
Code: [Select]
-XXX--XXXX--XXXXX-XXXXX-XXXXX-XXXXX-
so:
Code: [Select]
-- -- -- -- -- -- -- ----- FF 00 01 02 FE 02 03
04 05 06 FE 02 07 08 09-0A 0B FF 0C 0D 0E 0F 10
FF 11 12 13 14 15 FF 16-17 18 19 1A FF
Note: yes, there's a column of empty space on the right-hand side. Shiva #1 technically only needs a 5x6 space, but 5x6 doesn't naturally exist in the size table, plus Shiva #2 does need the 6x6, so this was the cleaner way to go about it.

Shiva #2 uses Special size 93, which uses the 13th (hex) arrangement pointer at 75126: B5 D5
D5B5 + 68200 = 757B5

Like the situation with Indra, Shiva #2 uses the same two bottom rows of sprites as Shiva #1, so:
Code: [Select]
--XXX-
XXXXXX
XXXXXX
XXXXX-
OOOOO-
OOOOO-
or
Code: [Select]
--XXX-XXXXXXXXXXXXXXXXX-OOOOO-OOOOO-
written as:
Code: [Select]
-- -- -- -- -- FE 02 1B-1C 1D FF 1E 1F 20 21 22
23 24 25 26 27 28 29 2A-2B 2C 2D 2E FF 11 12 13
14 15 FF 16 17 18 19 1A FF

Shiva starts as size 92 and shifts to sprite 13, or "19" in base-10 (as displayed in Ff4kster), then reverts back to sprite 12, or "18" in base-10.

There ya go.
I'm going to start working on The tutorial for changing summon images tonight, but don't know if I'll get through it...

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Re: Fun with Summons
« Reply #6 on: October 17, 2013, 09:26:58 PM »
Hmm, so far the only way to add Summons is to remove current images? Can the images that were changed be relocated? (Like Cagnazzo on one of the unused Monster slots?) or are they set in stone?

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #7 on: October 17, 2013, 09:58:51 PM »
The problem you'd face is that there are a limited number of Special sizes.

Bear in mind, you're not taking over Mist, Valvalis and Kainazzo's monsters in these examples, you're taking over their image arrangements.

There are only 40 (hex) special sizes to work with...

I think B1 and B2 are completely unused (both are a tiny 3x1 rectangle). Beyond that, you could also do away with a few of Octomamm's eight forms. That's a bit excessive.
All the rest of the special sizes are pretty essential to the game the way it normally works (you can view them all in my post here if you'd like to see for yourself).

If you can live with only 4 Octomamm formations (I've probably never seen more than three or four anyway), then four of those plus B1 and B2 are enough to make Shiva, Indra and Jinn... so there you go.

If you wanted to fight chocobos and sylphs, you could use regular sizes for them, since their images are naturally rectangular - as long as you can live with them not moving.

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #8 on: October 17, 2013, 11:30:26 PM »
Alright, here we go...
How to change Imp into Shadow

The first thing to know is that there really are very few similarities between how enemy monster sprites are arranged and how summoned monster sprites are arranged.
Enemy monsters are given a defined rectangle, then the sprites are filled in either in order or out of order, and with or without empty spaces, as specified.
There's an extra step for summoned monsters. Summoned monsters are assigned a rectangular space, then are assigned an arrangement of 2-sprite x 2-sprite tiles (in or out of order, and some of which can themselves be empty spaces as specified), then those tiles are filled in with sprites and/or empty spaces in order or out of order as specified.
So Imp's image is first defined as an arrangement of tiles within a given rectangle - specifically, a "2x2" rectangle (that's 2-tiles x 2-tiles, not sprites), which looks like this:


Then, within those tiles, a sprite arrangement is specified:


A few points worth mentioning here.
Notice that these arrangements all seem to work in reverse order. This is related to the fact that a summon's image is inverted over the y-axis (because it's on your side, not the enemy's). When visualizing your summon image, it may help to imagine what it would look like if you were attacked from behind - or if you were fighting against it.

In the game's original programming, all Summon image tiles are numbered with ones and tens places as multiples of 2. The enumeration of the tile tells the game where to display the sprites in a sprite arrangement. Sprite 00 will always appear in the top right corner (unless back-attacked) of tile 00. If there is no tile 00, sprite 00 will not appear. Tile XY will always contain sprites XY, XY+1, X+1Y, and X+1Y+1.

There is no restriction, by the way, that says "the top row of tiles must only be numbered 0x, the second row must be numbered 2x, etc."
Hypothetically, Imp's tiles could be arranged like this:


The resulting summon would appear like so:

This is important to know when creating larger summon images, because sprites in a summon image can only be numbered 00-7F. Anything 80 or higher will represent an empty space in the place of itself minus 80.
The application is - when you're trying to summon a monster that's taller than 8 sprites (as Shadow is), you'll need to do something like putting tiles numbered 0x in the second row as well as the first.

One more topic to cover in the information download before we get into how to use all of this: Empty spaces. As previously stated, both tiles and sprites can be designated as empty spaces. To make an empty sprite, add 80 to the value of the sprite you want to make empty. It's very important to note, though, that doing this will not just skip over that sprite. What it will do is essentially skip a space and push all sprites forward by one.
So,

Would appear as:


This has to do with how the game loads sprites to display. The sprite arrangement data tells the game, "put the first sprite here, the second sprite there, the third there..." and all of those places are defined spaces within the tiles.
The grid above tells the game, "Put the first sprite in the first spot, the second sprite in the second spot, an empty space in the third spot, the third sprite in the fourth spot..."
In order to get this:

(with an empty space that does not push the rest of the sprites forward), you'd have to specify in your sprite arrangement that the third sprite be placed in an unused location (I used 40), then stick an 82 at the end, after all sixteen sprites were assigned.

Now, just as a sprite arrangement can contain empty sprites, a tile arrangement can contain empty tiles, as well. This is a bit easier to visualize than empty sprites. An empty tile does not push the rest of the tiles forward - It simply puts an empty space where a tile would normally be. This is used quite a bit for summoned monsters that don't fill a rectangular area as a space saver (and for animated summons, as a way to conserve valuable tiles and sprites for multiple images). To place an empty tile, simply use FF.
A tile arrangement that looks like this:

Will yield a summon that looks like this:


It should also be mentioned that placing FE in a tile arrangement has it's own distinct effect. An FE tile tells the game to stop displaying all subsequent tiles.
So

will appear like this:

I'm not sure why this exists, or how I stumbled upon it, to be honest. It's never used in the original programming. I guess if you wanted to make a custom animated summon that starts as a TinyToad and turns into a ToadLady, or something like that, this would save you some tiles and sprites. Nice to know, I guess... We won't be doing anything that complicated here, but feel free to experiment.

The last thing I should probably explain here is how all of this arranging actually works in ROM. Obviously, you aren't drawing little spreadsheet files in your hex editor. The images in this tutorial are displayed as such because that is how I need to arrange them visually in order to easily write them out in my hex editor. If you can do this all without these steps, well, have fun saving the humans from the Matrix, Neo.
When planning a rectangular monster's image for summoning, the first step I take is to plot out where I need sprites in a Notepad file. So for Imp:
Code: [Select]
XXXX
XXXX
XXXX
XXXX
Then, I figure out how those sprites will fit into a tile arrangement. Easy enough in this case:

Now to write this out, we simply write these bytes out as they appear, left to right and top to bottom:
Code: [Select]
02 00 22 20As with Special size tile arrangements (finally, a similarity!), you don't need to specify when to start a new row, or when to stop, because you're working in an already-defined rectangular space. Since the summon image is defined as 2x2 tiles, the game will go to the second row after the second tile, and will stop displaying tiles after the fourth.

Once you've figured out how your tiles will be arranged, this will pretty much dictate how your sprites will be arranged - as long as you're working with a standard rectangular monster (a non-Special size) and not animating. I haven't (yet?) learned how to control summon animations, so that's a big yes-and-yes in this tutorial.
The tile arrangement above will always result in this sprite arrangement:

This, however, will be written right to left and top to bottom, so:
Code: [Select]
00 01 02 03 10 11 12 13-20 21 22 23 30 31 32 33
FF
I'm not sure if the FF at the end is needed, by the way, but it's always used, so I've never tried not to.

That's all for today. Practical application will be next (actually making Shadow). That will be a new post. If anybody who's following this needs any clarification on anything that's been written so far, please let me know. I know this seems rather complicated, but it's actually easier than I think I'm making it sound.

Knowing how long this will take, there's no sense in me withholding data locations, so:

9FC59: table of summons' x-position, y-position, width, height (4 Bytes per summon)

6F860: Pointers for tile arrangement data (reverse order and add to 60200), one per summon image (so Shiva has two, etc)

6F89A: Tile arrangement data

6F460: Pointers for sprite arrangement data (reverse, add to 60200), one per summon (so Shiva only has one)

6f482: Sprite arrangement data

689F0: Pointers to summoned monster sprites (to find where to find them in Tile Layer, that is - again, reverse, add to 60200)
« Last Edit: October 20, 2013, 11:08:45 PM by chillyfeez »

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Re: Fun with Summons
« Reply #9 on: October 18, 2013, 07:25:03 AM »
Yeah, I kind of got lost in that last part a little... no matter, great work on this tutorial so far! Looking forward to the next part.

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #10 on: October 23, 2013, 02:05:16 PM »
Alright, here it is...
Turning Imp into Shadow

First thing to do is round up the necessary data. We'll need:
  • Shadow's rectangular size
  • Shadow's Palette
  • The beginning address of Shadow's sprite data

So of course, we'll first reference the table at 7CC00 to find this info. Shadow's entry (From the Bab-il docs) reads:
08 B5 A8 99
So,
Size 08
Pallette B5
Graphical pointer 99A8

Next, we reference the size table and find the ninth size (00 is the first), which is 06 0C. Now, remember that Summon image sizes are defined as a rectangle of 2x2 tiles, not sprites, so we'll need to cut these numbers in half to define summoned Shadow's size: 03 06

Next we'll take the graphical pointer to determine the beginning of Shadow's sprite data.
99A8 * 8 + 8200 = 4CD40 + 8200 = 54F40
(fyi - if you don't like math, you could just open Tile Layer and scroll through monster images until you find Shadow)

So, we have...
Size: 03 06
Palette: B5
Sprite data: 54F40

Notice anything about that sprite data address?
If you said, "it's less than 60200 and therefore impossible to point to," you win!
As I believe I've mentioned before, enemy monster graphical pointers are more versatile than those of summoned monsters, because the enemy monster's pointer is multiplied by 8. In fact, the only monsters that can be summoned without making major data changes are the original summoned monsters, CPU (and its li'l buddies), Zemus, and Zeromus (initial form). All other monsters' image data is earlier than 60200.

The fix? Copy the desired sprite data into an empty space that is higher than 60200 (and less than 70200).
Now, it just so happens that there is a huge block of empty data just after the end of Asura that can be used for this purpose.

(it's the red stuff)

This block is large enough to copy the image data of any monster (including EvilWall!), with the possible exception of final-form Zeromus. So, easiest thing to do is open up two instances of your ROM in Tile Layer, go to the empty block in one, and to Shadow in the other, then just copy and paste.


Next, we need to point to this new image location. In my version, I copied the image data to 6EB20.
So: 6EB20 - 60200 = E920
My pointer will read 20 E9.
So, at 689F0, change the "18 88" to 20 E9.

Next quick little step is to change the palette.
Shadow's palette is B5, so change the "00" at 7004C to B5.

Next, we jump to 9FC59 in our hex editor to define Shadow's size.
the first entry in this table (which belongs to Imp) is:
C8 44 02 02
The first two bytes refer to the summoned monster's beginning x and y position (with 00 00 being the top left corner). We will need to change this, but there's really no way of knowing the right values without a little trial and error, so leave this for now. The latter two bytes, 02 02, are Imp's size. Change these to 03 06, as previously determined. Now we have:
C8 44 03 06
Leave this as-is for now.

Now we get to the... erm... fun part.
It's time to start arranging tiles. Shadow, as we've already determined, is 3x6 tiles. If it was 3x3, we could just go
04 02 00 24 22 20 44 42 40 64 62 60
and call it a day.
But since Shadow is taller than that, we have to be a bit creative. You see, the next row in this pattern would be numbered 8x, and remember, sprites cannot be numbered higher than 7F. So instead, we will have two rows each of 0xs, 2xs, and 4xs.
In the end, our tile arrangement will look like:

Which will be written out left-to-right, top-to-bottom:
Code: [Select]
04 02 00 0A 08 06 24 22-20 2A 28 26 44 42 40 4A
48 46
Seems so simple when you put it that way, right? Wait! Do not just overwrite Imp's tile arrangement with this one. First of all, Imp shares a tile arrangement with Bomb and Chocobo, so changing one will change all. Secondly, this is a longer arrangement, so it will write over other arrangements as well. So what to do? Change Imp's arrangement pointer to point to another empty block of data. We're actually going to use the same empty block we used for Shadow's sprites. We used up a good deal of it for the sprite data, but there's still plenty of it left for what we're doing now. In case you're making a larger summon (like, say, EvilWall) and need more space, there's also a big empty block at 68448 (though in all, it's not quite as big as the one we're using now).
So anyway, I chose to place Shadow's tile arrangement at 6F3B0, so we also have to change Imp's pointer (6F860) to B0 F1 (6F3B0 - 60200 = F1B0).

Once your tile arrangement is set - and because we're dealing with a standard-size monster, the sprite arrangement is easy. Given what our tile arrangement looks like, our sprite arrangement will look like this:


Then, we'll just write that out in order, right-to-left (remember, this is backwards), top-to-bottom:
Code: [Select]
00 01 02 03 04 05 10 11-12 13 14 15 06 07 08 09
0A 0B 16 17 18 19 1A 1B-20 21 22 23 24 25 30 31
32 33 34 35 26 27 28 29-2A 2B 36 37 38 39 3A 3B
40 41 42 43 44 45 50 51-52 53 54 55 46 47 48 49
4A 4B 56 57 58 59 5A 5B
Just as before, we can't just overwrite Imp's data, so we're going to use some more of that big empty block. I chose to place the sprite arrangement at 6F3E0, so we have to change Imp's sprite arrangement pointer (6F460) from 82 F2 to E0 F1 (6F3E0 - 60200 = F1E0).

So that's mostly it. We still need to change the x,y location where Shadow appears, but the only way I know of doing that is by toying around with it until it looks right. That location in ROM, 9FC59, translates to 13FA59 in LoROM. It's probably easiest to tinker in-game. The values I chose were A8 24.

Of course, now you have this badass Shadow Dragon to summon... who then executes a goblin punch.
Next post, I'll discuss how to change Imp's goblin punch into Shadow's Demolish attack.
Again, let me know if any of this needs clarification. Otherwise, til next time!


« Last Edit: October 26, 2013, 07:50:07 PM by chillyfeez »

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Re: Fun with Summons
« Reply #11 on: October 25, 2013, 08:47:29 AM »
Deftly explained! Your edit to the previous post also clarifies a few things as well. Though with TileLayer how do you even get a semblance of the graphics to look proper? Embarrassingly I couldn't even manage that much.

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #12 on: October 25, 2013, 09:06:09 AM »
First of all, make sure you're viewing in SNES 3BPP (eight colors), then make the first color in the palette white, and the second color black. That should help quite a bit.
Another Tile Layer tip - some banks of monster sprite data are not aligned with others. For instance (and definitely good to know here), if you are viewing the summon images and you scroll up to where Shadow is, it won't display properly. That's because you'll be off-set by eight bytes. If you hold ctrl and use the left and right arrow keys, you can advance the data by one byte. So do that eight times. If the monster images you need are still not displaying right, do it eight more times. (Note that you won't have to do this if you jump right to the proper address by calculating it using the pointer)
Also, using the arrow keys without ctrl will advance data by one sprite (18 hex bytes), and holding shift and using the arrow keys will scroll through palettes (I don't know how it decides what palettes to use, but it will store your custom palettes).
« Last Edit: October 25, 2013, 09:15:20 AM by chillyfeez »

chillyfeez

  • FF4 Hacker
  • *
  • Posts: 1,285
  • Gender: Male
  • Go ahead, ask me about Angel Feathers!
    • View Profile
Re: Fun with Summons
« Reply #13 on: October 26, 2013, 01:07:24 PM »
So now we have a summon-able Shadow, but he does not cast the right spell. Total bummer. You might think that the easy fix to this would be to simply change the AV properties of Imp to match those of Demolish. Well this works... sort of... not really. Shadow will appear and cast Demolish, but then he will not disappear. Worse still, if the battle isn't over by the end of your very next attack, the game will be frozen. This is because the instructions to make the summoned monster disappear and make the party reappear are included in the AV routine of the summon spell.

I've devised two different ways to fix this problem - the quick-and-easy way, and the slightly-longer-but-also-with-a-prettier-result way.

When you summon Imp, this is the AV routine the game executes (after the monster appears):
Code: [Select]
(4D Imp)
$02/EB54 9C 2B F4    STZ $F42B  [$7E:F42B]   
$02/EB57 6C 00 00    JMP ($0000)[$02:EE5B]   ;$0000 will be set to a different location based on what value is set for the spell's AV Sequence
$02/EE5B A0 80 E3    LDY #$E380             
$02/EE5E 20 2E EE    JSR $EE2E  [$02:EE2E]   
$02/EE61 22 71 F3 01 JSL $01F371[$01:F371]   ;this is the jump to the actual AV sequence
$02/EE65 4C 89 BE    JMP $BE89  [$02:BE89]   
$02/BE89 20 04 E7    JSR $E704  [$02:E704]   
$02/BE8C AD 5A F3    LDA $F35A  [$7E:F35A]   
$02/BE8F F0 17       BEQ $17    [$BEA8]     
$02/BE91 A9 FF       LDA #$FF               
$02/BE93 8D 20 F3    STA $F320  [$7E:F320]   ;this makes the summoned monster disappear
$02/BE96 20 76 F2    JSR $F276  [$02:F276]   
$02/BE99 20 13 85    JSR $8513  [$02:8513]   
$02/BE9C 20 34 C7    JSR $C734  [$02:C734]   
$02/BE9F 9C 5A F3    STZ $F35A  [$7E:F35A]   
$02/BEA2 9C 20 F3    STZ $F320  [$7E:F320]   ;this makes the party reappear
$02/BEA5 20 52 C7    JSR $C752  [$02:C752]   
$02/BEA8 60          RTS                     

You will NEED to use Geiger's SNES9x Debugger in order to perform either method, and Ff4kster is recommended, too.

OK, the Quick-and-Easy way:
Figure out which summon spell you want to replace (in this example, (4D) Imp, but this will work for all summons). We'll call this the "Source" spell for the sake of consistency in this tutorial. And which summon spell you want to replace it with (in this example, Demolish). We'll call this the "Target" spell.
-Set a breakpoint to when the game executes $2EB54.
-Cast the Source spell
-At the break, click Jump Over until you see a "JSL" instruction
-Record this instruction - it will be four bytes, "22 XX XX XX"
-Keep the breakpoint set
-Cast the Target spell
-Again, at the break, Jump Over until you see a JSL
-Record this instruction
-Replace the JSL in the Source spell with the JSL of the Target spell
The result (in the case of Imp -> Shadow) will look like this (the difference is at $02/EE61):
Code: [Select]
(4D Imp)
$02/EB54 9C 2B F4    STZ $F42B  [$7E:F42B]   
$02/EB57 6C 00 00    JMP ($0000)[$02:EE5B]   ;$0000 will be set to a different location based on what value is set for the spell's AV Sequence
$02/EE5B A0 80 E3    LDY #$E380             
$02/EE5E 20 2E EE    JSR $EE2E  [$02:EE2E]   
$02/EE61 22 B9 F3 01 JSL $01F3B9[$01:F3B9]   ;this is the jump to the actual AV sequence
$02/EE65 4C 89 BE    JMP $BE89  [$02:BE89]   
$02/BE89 20 04 E7    JSR $E704  [$02:E704]   
$02/BE8C AD 5A F3    LDA $F35A  [$7E:F35A]   
$02/BE8F F0 17       BEQ $17    [$BEA8]     
$02/BE91 A9 FF       LDA #$FF               
$02/BE93 8D 20 F3    STA $F320  [$7E:F320]   ;this makes the summoned monster disappear
$02/BE96 20 76 F2    JSR $F276  [$02:F276]   
$02/BE99 20 13 85    JSR $8513  [$02:8513]   
$02/BE9C 20 34 C7    JSR $C734  [$02:C734]   
$02/BE9F 9C 5A F3    STZ $F35A  [$7E:F35A]   
$02/BEA2 9C 20 F3    STZ $F320  [$7E:F320]   ;this makes the party reappear
$02/BEA5 20 52 C7    JSR $C752  [$02:C752]   
$02/BEA8 60          RTS                     
Note that this will only change the animation and the sound effect. you still have to change the sprites of (4D)Imp to match those of Demolish, and if you want to change the sound effect for some reason, you still need to change Demolish's sound effect.

So this works, and is a perfectly fine fix to the problem at hand. What I noticed, though, is that it eliminates the part of the summon where the monster moves forward, blinks and moves backward again. Apparently, those instructions are built into Imp's "actual" AV routine, so I dug a bit deeper and figured out...

The slightly-longer-but-also-with-a-prettier-result way

Here is  a deeper disassembly of Imp's AV routine:
Code: [Select]
Main Routine
$01/F371 20 A1 FD    JSR $FDA1  [$01:FDA1]   Move Forward
$01/F374 20 17 F3    JSR $F317  [$01:F317]   Move a little more forward, "attack" (blink like a monster attacking)
$01/F377 20 CF E9    JSR $E9CF  [$01:E9CF]   (unknown)
$01/F37A 20 67 F3    JSR $F367  [$01:F367]   Spell animation
$01/F37D 20 B1 FD    JSR $FDB1  [$01:FDB1]   Move backward
$01/F380 6B          RTL     

Move Forward
$01/FDA1 A2 08 00    LDX #$0008              Change this value to change how far forward Imp moves (Higher value, farther movement)
$01/FDA4 20 09 EE    JSR $EE09  [$01:EE09]   Essentially, move one pixel forward
$01/FDA7 CE 21 F3    DEC $F321  [$7E:F321]   
$01/FDAA CE 21 F3    DEC $F321  [$7E:F321]   
$01/FDAD CA          DEX                     
$01/FDAE D0 F4       BNE $F4    [$FDA4]
$01/FDB0 60          RTS                   

Move a little more forward, "attack" (blink)
$01/F317 64 4E       STZ $4E    [$00:004E]   
$01/F319 20 09 EE    JSR $EE09  [$01:EE09]   Same "move one pixel forward" subroutine, except here it causes the blinking, too
$01/F31C A5 4E       LDA $4E    [$00:004E]   
$01/F31E 29 04       AND #$04               
$01/F320 4A          LSR A                   
$01/F321 4A          LSR A                   
$01/F322 D0 05       BNE $05    [$F329]     
$01/F324 A9 34       LDA #$34               
$01/F326 4C 2B F3    JMP $F32B  [$01:F32B]   
$01/F329 A9 38       LDA #$38               
$01/F32B 8D 30 F3    STA $F330  [$7E:F330]   
$01/F32E E6 4E       INC $4E    [$00:004E]   
$01/F330 A5 4E       LDA $4E    [$00:004E]   
$01/F332 C9 10       CMP #$10               
$01/F334 D0 E3       BNE $E3    [$F319]     
$01/F336 A9 38       LDA #$38               
$01/F338 8D 30 F3    STA $F330  [$7E:F330]   
$01/F33B 60          RTS             

Spell Animation
$01/F367 A9 20       LDA #$20               
$01/F369 8D C2 F0    STA $F0C2  [$7E:F0C2]   
$01/F36C 22 D6 F9 02 JSL $02F9D6[$02:F9D6]   If you want to keep the summoned monster's movement but change the animation, change the JSL here
$01/F370 60          RTS 

Move Backward
$01/FDB1 A2 08 00    LDX #$0008              Change this value to change how far Imp moves backward
$01/FDB4 20 09 EE    JSR $EE09  [$01:EE09]   Same subroutine again controls backward movement. I took a cursory look, but I can't understand how.
$01/FDB7 EE 21 F3    INC $F321  [$7E:F321]   
$01/FDBA EE 21 F3    INC $F321  [$7E:F321]   
$01/FDBD CA          DEX                     
$01/FDBE D0 F4       BNE $F4    [$FDB4]     
$01/FDC0 60          RTS   

Slightly off-topic here... you can change how far forward and backward Imp/Shadow moves by changing those LDX values, but beware that other summons use the same subroutines. Cockatrice uses both the Move Forward and Move Backward instructions, and Bomb uses the Move Forward. They may be used by others as well. I have not fully tested.

Anyway, the key here is within the Spell Animation subroutine. Again, there is a JSL that jumps to an AV routine. If you want to change the spell animation without bastardizing the rest of the summon animation, this is the JSL that you want to change to that of Demolish.

And there you have it!

I'm pretty sure I have now imparted all knowledge I have about editing summons. Grimoire LD mentioned in another thread recently that other summon animation instructions are affected by changing the spell's AV "effects." I haven't done any research on this yet, though, and I think I'm going to take a break from Summon research at least for a while.

As previously stated, let me know if there's any points here that need clarification. For those of you who have been following along, sorry that what I originally thought would be a "week or so" ended up taking me about 2 1/2 weeks. I guess I really had no idea how long this process would take to explain. This will be the last formal tutorial on this thread, at least for a long while.
 :sleep:

Grimoire LD

  • FF4 Hacker
  • *
  • Posts: 1,684
    • View Profile
Re: Fun with Summons
« Reply #14 on: October 27, 2013, 07:58:52 PM »
Now that last part is very impressive! It is probably the first recorded instance of someone delving into the actual data of possibly sequence/pointers.

Incredible work Chillyfeez!