øAslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&action=printpage;topic=1892.0e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/indexf6dc-2.htmlslickproductions.org/forum/index.php?PHPSESSID=5f0fck550j2m4m2fpbtkj2vkm1&topic=1892.0e:/My Web Sites/Slick Productions - FFIV Message Board/slickproductions.org/forum/indexf6dc-2.html.zx2Fg^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ`¦D"wOKtext/htmlISO-8859-1gzip0|Ö"wÿÿÿÿÿÿÿÿTue, 10 Mar 2020 08:04:25 GMT0ó°° ®0®P®€§²ð®1Fg^ÿÿÿÿÿÿÿÿ #"w Print Page - Whose turn is it?

Board of Slick

Library of the Ancients => Final Fantasy IV Research & Development => Topic started by: chillyfeez on October 30, 2013, 09:55:27 AM

Title: Whose turn is it?
Post by: chillyfeez on October 30, 2013, 09:55:27 AM
Does anybody have any insight into how the game determines when a character's turn comes up in battle?
I imagine it makes calculations based on the Relative Speed values, but based on the fact that there will be times in battle when nobody is doing anything, it can't just be a turn queue (like in FFX or FFT).

So I imagine there must be timers counting down to each character's turn... anybody know where in RAM those are? Or have an idea about how to start looking for them?

Or maybe I'm totally off base and turns are determined some other way?
Title: Re: Whose turn is it?
Post by: Grimoire LD on October 30, 2013, 11:33:15 AM
An interesting idea Chillyfeez, I suspect that it is an invisible ATB gauge that counts up until that person's turn is reached. I'll see if I can't find anything more concrete...

Hmm, well just by simple mathematic I think that Yousei must have been off on his relative speed dealings.

Cecil's Agility x 32 / Character's Agility x 0A if it is Cecil's case it should Always Equal 03, but the value that seems to be consistent is that it is 5 no matter what.

But if it is reading another character, then it might make sense...

A level 1 Rydia with 4 Agility who is in a party with a 99 Agility Cecil has EF01 as her Relative Speed.

99 x 32 = 3168 / 4 x 10 = 40. 3168 /40 should only be 79. But EF+(255x1)01 is 495.

She'll get one turn to Cecil's 20 it seems.

This is definitely worthy of further exploration.

Title: Re: Whose turn is it?
Post by: chillyfeez on October 30, 2013, 01:36:34 PM
What I'm trying to be able to do is force (or delay) a single turn, without affecting the character/monster's speed otherwise. The end result would be a new attempt at making a Mime command (I can't just let this die) by using the Charging status from Yang's Charge ability, which sets a next action and a status that executes that action next turn. If I could force that next turn in the same command...
Well, that's the idea, anyway. The method's all worked out in my head, except I can't force the turn.
Of course the possibilities of what we could do with this wouldn't end there... wasn't there a Charge command in FFV that made all party members attack? We could do something like that, too. Maybe even an X-Magic...
Title: Re: Whose turn is it?
Post by: chillyfeez on November 01, 2013, 11:58:03 AM
Aha!
Found the hidden ATB gauge.

Turns out the Bab-il docs are wrong, or at least incomplete. They say that the data at 2A04-2A2A is "status duration data for each slot," and that 2A2B-???? is "poison data."
Well, some of this might be true, but here is what I've found out for sure...
Beginning at 2A05, there are 15 (hex)-byte records for each battle participant (beginning with the five party slots, then on to monsters). Byte 02 of this record counts down until it is time for the character/monster to do something. This counts for when he/she/it is ready to take a turn, or if casting, when he/she is ready to cast the spell. Everybody's timer counts down at the same rate, and the beginning number is higher depending on relative speed (or, presumably, casting duration of the spell).

More research and testing is needed before I can say that I can use this info in custom commands to force or delay an individual's turn, but it is definitely possible to do so by hand with Geiger's.

Also, byte 04 has something to do with what the character is doing during that wait. 80 is "waiting for command." 00 is either "defend," or simply "waiting for next turn." It seems having bit 0 set freezes the timer altogether, thus making the character unable to take a turn (which does not freeze the game, but appears to be permanent through the end of the battle.

Interesting stuff...
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 01, 2013, 04:07:58 PM
Wow! Great work there Chillyfeez! I'll have to scrounge around that area a bit and see if I can't help with figuring this out.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 01, 2013, 05:25:58 PM
I'm not able to mess with it too much today, but my guess is that the timer isn't set until after the command takes place, so changing the value it starts at probably will require affecting the factors that determine that number instead of something as simple as setting the number within the instructions of a command (if that makes any sense).
Title: Re: Whose turn is it?
Post by: chillyfeez on November 04, 2013, 11:08:09 AM
Made some exciting strides on this one!

Remember that byte 04 I was talking about? Well, if it's set to 08, then when the timer reaches zero, the character will do whatever action is in their "next [or most recent] action" byte.
You can test this out to see. Load your game in Geiger's and get into a battle. View RAM at 7E2A04. You'll see the counters. You'll have to perform an action with a character first. After that, their "charging status" byte will turn to 00 (it's the second byte after the timer). Change it manually to 08. When the timer reaches zero, the character will automatically perform that same action again.
Notice that both Jump and Charge/Boost/(whatever) contain these three commands in succession:
Code: [Select]
20 C8 85  JSR $85C8
A9 08     LDA #$08
9D 06 2A  STA $2A06,x
Well, subroutine 03/85C8 identifies which character to address in the duration table. Then the next two commands put 08, or "automatically perform 'next action,'" in the appropriate byte for that character.

Also, there is a table in ROM at A0189 that contains one-byte-per-command references to the duration set to perform each command. Most of them are 00, which is immediate. 01 is not one second, though. These are pointers. I haven't tested all 256 options (and probably won't) but the following are used:
00: (most commands) immediate
01: (Charge) 5 seconds
02: (Dark Wave, a few others) 2 seconds
04: (Salve, Aim) 1 second
FE: (not used, but I tested it to see if it would crash the game - it doesn't) several hundred seconds

I am nearly positive that with this knowledge, I have enough to make my Mime command! Might take a few days to get it working...
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 04, 2013, 12:22:51 PM
That is Awesome! Incredible work there Chillyfeez! Finally now we can add wait timers to some commands that should have them to begin with, I was looking for the elusive "timer" bytes, but I expected them to be in the command routines themselves, not in a completely separate part of ROM.

Again, well done! That would make a very neat little addition to the editor.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 06, 2013, 12:10:56 AM
Hmm... seems I'm still missing a key portion of the Jump and Charge routines that causes the 08 timer status to stick after they return. Think I'm gonna have to test Charge command-by-command til I find it. Ah, well. I'll get there eventually. Really hope I can find the time sooner rather than later.
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 06, 2013, 12:30:34 AM
Hmm...

http://slickproductions.org/forum/index.php?topic=1883.msg19350#msg19350

Is this of any help in that? Charge and Jump's second portion does make it go through the Fight Routine which would likely reset the timer all on its own.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 06, 2013, 08:10:18 AM
I've been referring heavily to your disassemblies for this process. I actually haven't tried changing Charge's 1F to see if it works with other commands. I'm kind of afraid to find out...
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 06, 2013, 11:24:31 AM
Charge and Jump's secondary command can be changed (Though Jump's might be a bit finnicky because of the "coming back down" animation that is used in that. Charge I've tested pretty extensively the only problem with it is that the Charging Status never goes away because it is the 1F command that removes it, itself. There are benefits and downsides to having Charge status though. Mainly Charge has an innate x2 damage with the status but has Defense and Magic Defense cut in half. This, in my opinion, more fits Berserk, than it does Charging which never should have had those restrictions placed on it in the first place.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 06, 2013, 12:02:21 PM
Do you happen to know the purpose of INC $390A?
Jump and charge both use that, too, but the RAM map in the Bab-il docs does not identify 7E390A. I have a day off tomorrow so I've resolved to figure it out then.
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 06, 2013, 12:18:31 PM
Not only Jump and Charge, but Regen uses it as well. The information around 390A is mostly stuff dealing with stats.
3901      Caster's Critical Hit Bonus
3902      Caster's Attack Power

3904      Target's Magical Defense Rate
3905      Target's Physical Defense Rate

I've never given it much thought, but it may be more important than it seems.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 06, 2013, 05:21:17 PM
Regen, too... as in, another command that sets an automatic next command? I bet that's part of the puzzle! Thanks for the info!
Title: Re: Whose turn is it?
Post by: chillyfeez on November 07, 2013, 12:42:36 AM
IT WORKS!
That was it - 7E390A. Somehow, setting that to 01 instead of the default 00 makes the game not reset the 08 timer status after the command is finished.
As a result, I now have a fully-functional Mime command! I'll clean up the code a bit tomorrow (I think I can cut out a few unneccessary commands) then post it for all to enjoy.
If there's any interest out there, I could make a patch that changes the game-crashing Dummy command into Mime. Would anyone want that? (I'll post the disassembly, too, of course)
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 07, 2013, 12:47:52 AM
That sounds fantastic! I'm glad to see everything worked out well in the end. I wouldn't mind giving a Mime a spin.
Title: Re: Whose turn is it?
Post by: xcmn on November 07, 2013, 11:56:11 AM
Please do. I'd love to have it in a hack. I'm especially keen on the humor a mime presents to the storyline.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 07, 2013, 11:20:06 PM
Well, "cleaning the code up" took a long time, and ended up making the code about twice as long - but I believe I accounted for all instances that would make the command screw up.
The patch is attached. Apply to a headered 1.1 FFIIUS ROM (won't work on any others). This will turn the Dummied "makes game crash" command (the one after Peep) into Mime.
The only typically available commands that can't be mimed are Gird, Cover and Hide - Plus Mime itself. All spells (including summons) will Mime perfectly but will cost the appropriate amount of MP (so test on a character with MP). Throw and Item work fine as well (miming item may not expend the item...).
You can only Mime party members - Miming monsters will fail (but you can use my Copy command (http://slickproductions.org/forum/index.php?topic=1883.132) to copy monsters' attacks).

Here's the disassembly:
Code: [Select]
$03/FEF0 C2 20       REP #$20               
$03/FEF2 A6 A6       LDX $A6    [$00:06A6]   ;Load active character's slot into x
$03/FEF4 E2 20       SEP #$20               
$03/FEF6 AD 51 27    LDA $2751  [$00:2751]   ;Load target's last action used into A
$03/FEF9 C9 0F       CMP #$0F                ;Is it Gird?
$03/FEFB F0 71       BEQ $71    [$FF6E]      ;If so, jump to the end (fail mime)
$03/FEFD C9 13       CMP #$13                ;Is it Cover?
$03/FEFF F0 6D       BEQ $6D    [$FF6E]      ;If so, jump to the end (fail mime)
$03/FF01 C9 09       CMP #$09                ;Is it Hide?
$03/FF03 F0 69       BEQ $69    [$FF6E]      ;If so, jump to the end (fail mime)
$03/FF05 C9 15       CMP #$15                ;Is it Mime?
$03/FF07 F0 65       BEQ $65    [$FF6E]      ;If so, jump to the end (fail mime)
$03/FF09 C9 22       CMP #$22                ;Is it Regen-in-progress?
$03/FF0B D0 04       BNE $04    [$FF11]      ;If not, skip to next check
$03/FF0D A9 19       LDA #$19                ;If so, change to Regen
$03/FF0F 80 1E       BRA $1E    [$FF2F]      ;Then jump past this round of checks
$03/FF11 C9 20       CMP #$20                ;Is it Twincast?
$03/FF13 D0 04       BNE $04    [$FF19]      ;If not, skip to next check
$03/FF15 A9 02       LDA #$02                ;If so, change to Spellcast
$03/FF17 80 16       BRA $16    [$FF2F]      ;Then jump past this round of checks
$03/FF19 C9 1E       CMP #$1E                ;Is it Jump's return?
$03/FF1B D0 04       BNE $04    [$FF21]      ;If not, skip to next check
$03/FF1D A9 06       LDA #$06                ;If so, change to Jump
$03/FF1F 80 0E       BRA $0E    [$FF2F]      ;Then skip past this round of checks
$03/FF21 C9 1F       CMP #$1F                ;Is it Charge's return?
$03/FF23 D0 04       BNE $04    [$FF29]      ;If not, skip to next check
$03/FF25 A9 0D       LDA #$0D                ;If so, change to Charge
$03/FF27 80 06       BRA $06    [$FF2F]      ;Then skip past this round of checks
$03/FF29 C9 1C       CMP #$1C                ;Compare to Show
$03/FF2B 90 02       BCC $02    [$FF2F]      ;If an earlier command, then continue
$03/FF2D 80 3F       BRA $3F    [$FF6E]      ;If Show or later, jump to the end (fail mime)
$03/FF2F 9D 51 20    STA $2051,x[$00:2051]   ;Store A in active character's next action
$03/FF32 AD 52 27    LDA $2752  [$00:2752]   ;Load target's last spell used into A
$03/FF35 C9 4D       CMP #$4D                ;Compare to (uncastable) Imp
$03/FF37 90 17       BCC $17    [$FF50]      ;If an earlier spell, skip past this round of checks
$03/FF39 C9 5A       CMP #$5A                ;Comepare to (uncastable) Asura #1
$03/FF3B B0 05       BCS $05    [$FF42]      ;If yes or higher, skip ahead
$03/FF3D 18          CLC                     
$03/FF3E E9 1B       SBC #$1B               
$03/FF40 80 0E       BRA $0E    [$FF50]      ;If (uncastable) Imp through (uncastable) Leviatan, then switch to the castable version and skip past the rest of these checks
$03/FF42 C9 5D       CMP #$5D                ;Compare to (uncastable) Bahamut
$03/FF44 B0 04       BCS $04    [$FF4A]      ;If yes or higher, skip ahead
$03/FF46 A9 3E       LDA #$3E                ;If (uncastable) Asura #1, 2 or 3, then change to castable Asura
$03/FF48 80 06       BRA $06    [$FF50]      ;Then skip past the rest of these checks
$03/FF4A C9 5E       CMP #$5E                ;Is it higher than (uncastable) Bahamut?
$03/FF4C B0 02       BCS $02    [$FF50]      ;If so, skip ahead
$03/FF4E A9 3F       LDA #$3F                ;If (uncastable) Bahamut, change to castable Bahamut
$03/FF50 9D 52 20    STA $2052,x[$00:2052]   ;Store A in active character's next spell to cast
$03/FF53 AD 53 27    LDA $2753  [$00:2753]   
$03/FF56 9D 53 20    STA $2053,x[$00:2053]   
$03/FF59 AD 54 27    LDA $2754  [$00:2754]   
$03/FF5C 9D 54 20    STA $2054,x[$00:2054]   ;Load target's last target into A, then store A into active character's next target
$03/FF5F A9 03       LDA #$03               
$03/FF61 20 C8 85    JSR $85C8  [$00:85C8]   
$03/FF64 A9 08       LDA #$08               
$03/FF66 9D 06 2A    STA $2A06,x[$00:2B46]   
$03/FF69 EE 0A 39    INC $390A  [$00:390A]   ;Apply the status that makes active character automatically take next action
$03/FF6C 80 0F       BRA $0F    [$FF7D]      ;Then skip ahead 
$03/FF6E A9 00       LDA #$00               
$03/FF70 8D CA 34    STA $34CA  [$00:34CA]   
$03/FF73 A9 F8       LDA #$F8               
$03/FF75 8D C6 33    STA $33C6  [$00:33C6]   
$03/FF78 A9 03       LDA #$03               
$03/FF7A 8D C7 33    STA $33C7  [$00:33C7]   ;Display "Nothing Happened."
$03/FF7D A9 DB       LDA #$DB               
$03/FF7F 8D C4 33    STA $33C4  [$00:33C4]   ;Apply the "Parry" stance
$03/FF82 60          RTS   

Because of the length of the code, I couldn't simply use Grimoire LD's shortened Peep extra space, because it takes up too much space. I discovered, though, that the last ~110 (hex) bytes in the 30000s (LoROM) are free, so that's where the Mime code is.

Oh, by the way, the only change this patch will make is to create Mime - you'll still have to assign the command to a character.

Enjoy!
Title: Re: Whose turn is it?
Post by: chillyfeez on November 08, 2013, 12:13:28 AM
By the way, Grimoire, any thoughts from your research on why "Nothing happened" isn't happening?
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 08, 2013, 07:51:21 AM
I tried to delve into this a little but came up with little to no answer. All I can say is that ordinarily an 80 is put into 7E34C5 from very early in the command subroutines, (but not within their specific section) that without that there the game assumes there is no message. Try to plug an 80 in there with an instruction and see if that might solve the problem.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 08, 2013, 09:31:32 AM
Will do. Thanks.

... so that didn't work.
 :bah:

I'm gonna try looking into this a bit, but honestly, I don't think it matters enough to spend a whole lot of time on... who would want to mimic crappy commands like Gird and Hide anyway?
Title: Re: Whose turn is it?
Post by: chillyfeez on November 09, 2013, 12:50:56 PM
OK - Figured it out with a relatively simple fix - the disassembly and patch are updated in the post above.

For those interested, I followed the code from an unsuccessful jump (tried to jump on self for a guaranteed fail) to just outside of Jump's subroutine, then compared the trail with that of Fight and Mime. What I found was that Jump was loading "F8 03" into 7E33C6-33C7 somewhere before the subroutine, and Fight and Mime were not. Fight loads different values there, and Mime was loading nothing. So, I made a failed Mime load the same values a failed Jump does - Bingo! Now the player knows when a command can't be Mimed.
Title: Re: Whose turn is it?
Post by: Pinkpuff on November 10, 2013, 06:38:23 AM
Does this patch move anything around of any significance code wise? If so, saving with FF4kster might fool up something unexpectedly.
Title: Re: Whose turn is it?
Post by: chillyfeez on November 10, 2013, 09:31:08 AM
Granted I haven't updated my FF4kster since September or so, but the version I have is still compatible. The only thing this does is change a command pointer (the one for the unusable "game crash" command) and adds some code into a place that was previously all "FFs."
I would be concerned about how the patch might affect the version that you release once Grimoire is done breaking down his command editables that he is working on for you presently, since that deals directly with code in the battle commands (though none of what he is posting overlaps with any of the code in my Mime patch).
Title: Re: Whose turn is it?
Post by: Grimoire LD on November 10, 2013, 12:19:40 PM
Indeed, your patch doesn't really hurt anything in a default sense and uses unused (and wasted) resources all around. The one thing you did add to likely was the Command Pointer table (changing the 0000 for the Crash command), which is something the editor will likely never touch. It's nothing like tearing apart existing routines to make them work better for you, instead you added a while routine without swallowing up anything else, but even so these still work fine with FF4kster.