A Guide to Ability Learning - Printable Version +- FF6 Hacking (https://www.ff6hacking.com/forums) +-- Forum: Hacks, Resources and Tutorials (https://www.ff6hacking.com/forums/forum-1.html) +--- Forum: Narshe School (https://www.ff6hacking.com/forums/forum-14.html) +---- Forum: Assembly / Hex (https://www.ff6hacking.com/forums/forum-25.html) +---- Thread: A Guide to Ability Learning (/thread-729.html) |
RE: A Guide to Ability Learning - GrayShadows - 07-11-2020 (07-10-2020, 10:46 PM)madsiur Wrote:(07-09-2020, 03:00 PM)Mutteo Wrote: Is there a way to set Dance Learning by Level Up ONLY? I wanted to give this ability to Locke, but I didn't want him to learn them via the Battle Maps. If dances are listed in the order they're learned, as with Blitz and SwdTech, it's doable with only one 8-entry table of levels at which you learn a new dance. Blitz and SwdTech reference only their level-at-which-learned table in C2, for leveling up after combat, and the recruitment/level averaging code in C0 references that same table and a shared bitfield table (C0/A22C) that you could also use for learning Dances. RE: A Guide to Ability Learning - Mutteo - 07-18-2020 (07-10-2020, 10:46 PM)madsiur Wrote:So I have been at this for a week, and I.....have no idea what I'm doing. I appreciate your help on this, but I don't think I made much leeway on this.(07-09-2020, 03:00 PM)Mutteo Wrote: Is there a way to set Dance Learning by Level Up ONLY? I wanted to give this ability to Locke, but I didn't want him to learn them via the Battle Maps. I actually did not know of a NOP command. Honestly I tend to glance over words like BEQ or JSR in the coding. Anyway I was trying to do research on NOP commands and from my observation the byte is $EA. So I started by trying to change the first byte in every code of the Mog Dances, since commands strings I saw started with that byte. Code: C2/5EE5: EA 0A 30 LDA $300A Of course even if I did manage it correctly, I was unable to figure out how to change the dances to level up. The first problem is adding a new line of code to this Code: Who learns what at level up Code: Who learns what at recruitment I was able to find Terra's natural magic data at ECE3C0-ECE3DF as well as Celes's, Sabin's, and Cyan's. Using FF3USME I was able to make the comparison about each byte controlling the Level and Magic ID, which was about the only thing I was able to understand, though finding out which line of code is supposed to direct to this code of magic data I couldn't say. Even if I did, I am also left with the issue that Dance Abilities are different from individual spells so I could not find where the index is kept on them. You mentioned to me the Dance ID is $7E1D4C, but when I went to look for it on HXD, the number was too high. So then I thought maybe I need to subtract $C00000 to it and it's I found the number to be $-41E2B4, and that can't be right. Sigh, I am the fails... (07-11-2020, 10:39 PM)GrayShadows Wrote: If dances are listed in the order they're learned, as with Blitz and SwdTech, it's doable with only one 8-entry table of levels at which you learn a new dance. Blitz and SwdTech reference only their level-at-which-learned table in C2, for leveling up after combat, and the recruitment/level averaging code in C0 references that same table and a shared bitfield table (C0/A22C) that you could also use for learning Dances.I think so? I know the dances are organized in the same place in the command window. Of course knowing where anything is located is another story. RE: A Guide to Ability Learning - C-Dude - 07-19-2020 (07-18-2020, 08:40 PM)Mutteo Wrote: So I have been at this for a week, and I.....have no idea what I'm doing. I appreciate your help on this, but I don't think I made much leeway on this.Ooch, if you do this, you're going to have a bad time. NOP, or "No Operation", is a one-byte command. That means the processor reads it as 'hey, take a breath and then read the next byte'. However, you didn't NOP the rest of the former command, so it reads 0A as a new command instead of what it used to be... the little end of an address. That means it's interpreted as ASL, "Arithmetic Shift Left". The value of A is multiplied by 2. ASL is too a one-byte command, so the processor does this command and moves to the next byte, assuming it's a new command (instead of what it used to be... the big end of an address.) But the next byte is 30, which the processor reads as BMI, a conditional local jump "Branch if Minus". It checks A for the minus flag (that is, is the high-bit set, or is A greater than or equal to $80?), and branches if so. The distance it branches is determined by the value of the next byte, which is EA because you were trying to NOP the next line. ...The result? A gets arbitrarily checked if it is minus. If it is, the code jumps back -$12 bytes, likely ending up in the middle of OTHER code. The sequence of logic has no way to get back on-sequence, so the game unravels like a ratty sweater. If you're going to NOP a line, you need to replace each byte of that line with an EA. For instance, if you're removing LDA $300A, you need to replace all three bytes with EA. EA EA EA I want to reply to your other stuff too, but this is too important to be ninja'd. I'll edit in more as soon as I can. (07-18-2020, 08:40 PM)Mutteo Wrote: Of course even if I did manage it correctly, I was unable to figure out how to change the dances to level up. The first problem is adding a new line of code to thisCMP is 'Compare A', and is extremely important. It checks if A has a certain value, by subtracting the number that follows from it (without updating it) and setting the carry accordingly. For instance, if the current value in A is 7, and you CMP 6, then the result of the subtraction is 1 and the carry is not set (because 7 doesn't have to 'borrow' a number to subtract 6). If you took A is 7 and you CMP 8, then the result of the subtraction is -1 ($FF) and the carry IS set, as 7 was too small to subtract 8. Next, we need to discuss BNE and BEQ. BNE is "Branch if not equal". It checks if the result of a CMP is anything BUT 0. If it is, then it skips a number of bytes equal to the number that follows (forward if less than $80, backward if more than $80... to find out how many bytes backward, subtract the hex value from $100). BEQ is "Branch if equal", and does the same thing but only branches if the result of the CMP is 0. In the context of level learning, this method is used to check the identity of the character who is gaining the level. So, we need to insert a redirection to some freespace somewhere in this comparison list that will let us check if the character is Mog and handle him accordingly. Here's a trick I learned from Hatzen's patches: if you need to jump to new code or a subroutine and all the commands are two bytes long, the easiest way to insert something is to make the jump you use use 4 bytes total. That means it should be long-addressed. So, what we're going to do is overwrite Terra's check with a jump to freespace. Code: C2/61B9: C9 00 CMP #$00 (is it character #0, Terra?) Code: {Your freespace here.} RE: A Guide to Ability Learning - Mutteo - 07-19-2020 (07-19-2020, 01:49 PM)C-Dude Wrote: If you're going to NOP a line, you need to replace each byte of that line with an EA. For instance, if you're removing LDA $300A, you need to replace all three bytes with EA.Oooh, That makes much more sense now that I know what that command actually does. So yes I changed all the bytes in the offset $C25EE5-$C25EF0 to EA and that fixed that problem. Quote:C-DudeYou lost me on that, maybe an example would help cement that better. Phew, this reminds me of Calculus class in college, what a nightmare that was. Still, I shall try my best tackling this problem, let's see... So I was trying to incorporate the information you gave me regarding JMLs to both the Level Up check and the Recruitment Guides. I actually have free space at $D095F0-$D097FF (probably from allocating instruments or music data from my last project) so I used that for the Level up Guide. (I also used Locke, since I want him to learn Dance instead of Mog) Code: C0/A18E: C905 CMP #$05 (is character Sabin?) Code: C2/61B9: 5C 04 96 D0 JML $D09604 I'm just not sure how to create a Dance Learning Routine yet. RE: A Guide to Ability Learning - C-Dude - 07-20-2020 Sorry I was being too technical about the carry. There's a much easier way to explain it, if the number you're comparing against is larger than your current number, the carry is set. If it's smaller, the carry is not set. This won't be important for natural learning, but does come up in other ways, like if you want to check if it's at LEAST a certain character number (the code does this often to handle guests). After a CMP, you can throw all sorts of conditional situations at your code. BEQ (Branch if Equal) = The compared number and your number are the same. In this case, we've found the character we're looking for. BNE (Branch if Unequal) = The compared number and your number are different. For instance, if the game is running Celes's check, it will skip the Terra code. BCC (Branch if Carry Clear) = The compared number is smaller than your number. Or put another way, your number is bigger than the checked number. In this context, it could be used to check if the character is a guest. Not really important to your current goal, though. BCS (Branch if Carry Set) = The compared number is larger than your number. Sometimes used by the spell learning system to distinguish between Attack, Effect, and Healing spells, and has lots of uses elsewhere. Again, not so important to your current goal. As for your question, we'll be putting all of the relevant code to your tweak in the same space (this makes it easier to document, rather than having it all over the rom in bits and pieces), but the C0 jump will be going to a different spot than the C2 jump will. Let's build a learning dance subroutine! Code: {Pointers} Also... be ABSOLUTELY sure you have a copy of your ROM from before you started hexing stuff like this. You'll need it to make a difference patch to repair damages if something unexpected happens. In fact, once you think you've got it working, you should probably make that reversal patch right away. Using LunarIPS, select the hexed ROM as the original and your previous version as the "patch", and it'll give you a nice reversal patch that'll work so long as you don't do other stuff in that same section of the ROM. RE: A Guide to Ability Learning - Mutteo - 07-20-2020 (07-20-2020, 12:56 AM)C-Dude Wrote: I'm not sure this code will work, but I'm hopeful. You should try it and see if it does what you want; it's built on the principles I learned from GrayShadows' work (and from Assassin's and NovaliaSpirit's disassemblies). You'll also want to try counting the bytes for branches... when you see a D0 04, count the next four bytes to see that it's pointing to the command you want it to land on. For branches higher than $80, count up to $100 as you move backwards; when you hit $100 that's the byte the branch should be pointing to. Wow...I had no idea how much work it took to make a new learning subroutine. It's all so much to take in and understand every little detail that goes into coding. I may never be able to grasp how all this works. Even when I locate a string of code somewhere, I just get lost in a sea of bytes. I'd like to think that I learned some things today though. Anyway I plugged in all the information you gave me and it seems to be working fine as far as I can tell. I am extremely grateful that you went out of your way to do this for me. It is very much appreciated. I wish I could return the favor somehow, though coding is not my strong suit. RE: A Guide to Ability Learning - C-Dude - 07-20-2020 (07-20-2020, 09:55 PM)Mutteo Wrote: Anyway I plugged in all the information you gave me and it seems to be working fine as far as I can tell. I am extremely grateful that you went out of your way to do this for me. It is very much appreciated. I wish I could return the favor somehow, though coding is not my strong suit. No problem, I was glad to help. You've had the courage to actually attack the animation code (your harp thing), so you've got coding talents that I don't. I understand the hesitation, too, when I started just a year ago (or has it been two?) I wasn't even going to jump into this stuff: I thought it was like learning to speak robot. As for hacking assembly in hex, there are a lot of documents on the Wiki that will help explain what each op code is actually doing. https://www.ff6hacking.com/wiki/doku.php?id=ff3:ff3us:doc:snes If you're going to be doing more coding with hex, try to think of it like a logic flow chart. You've got a few variables (A, X, and Y mostly), you test to see if they've got the value you want, and then you modify or record something. In the case of the dance code above, we're basically doing the following: A) Making a copy of the "Learn SwdTech" code B) Replacing JSR $6222 with the block of code found at C26222, since we're in the D0 bank C) Replacing instances of $E6F490 with our Dance Level table, $D096A2 D) Replacing instances of SwdTech RAM location $1CF7 with the Dance RAM location $1D4C E) Replacing JMPs with JMLs to the appropriate spots, since we're in the D0 bank F) Making sure all short jumps (BNE, BEQ, BCC, BCS) are pointing to the starts of the right lines, since we had to insert extra bytes to make room for the JMLs relative to the code we're patterning. |