News: 11 March 2016 - Forum Rules, Mobile Version
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia

Author Topic: Debugging the Final Fantasy 1 Dynamic Action patch  (Read 2718 times)

essellejaye

  • Jr. Member
  • **
  • Posts: 27
    • View Profile
Debugging the Final Fantasy 1 Dynamic Action patch
« on: August 29, 2016, 03:04:04 am »
This is in reference to @CaptainMuscles:' dynamic actions patch:
http://www.romhacking.net/hacks/1769/

I ran into the same problem as @dudejo: in this thread:
http://www.romhacking.net/forum/index.php?topic=17295.0
I crashed after casting HEL3 while battling Kary.

Admittedly, I'm new to rom hacking and ASM, in fact the problem with this patch spurred me to go to nesdev and learn about the 6502. I like this patch and want to fix it, but if I can't then hopefully this info helps someone else who can.
Alright, enough rambling...

The reported behavior is that the game freezes whenever a physical attack (player or enemy) happens any time after an L5-8 spell is cast.
The actual problem is a bit more subtle. It's not a problem with combining patches, as it happens when the patch is applied to a clean FF1 image. I don't think it's a problem with how Cap coded the patch; I two different variations and got the same results.

Steps to reproduce:
It can be reproduced from a clean state as follows:
1) apply the patch to a clean FF1 NES image;
2) New Game, create a part with 4 mages of any type - this guarantees that your first action can access the MAGIC menu;
3) on your first turn, select MAGIC, and scroll down to the second page, then press B to cancel;
4) with that same character, select FIGHT, pick an enemy, press A to attack;
-> the attack lands, but the game freezes, including the music.
Attempting to run after viewing the L5-8 page also locked up the game.

Notice that the game crashes without having to cast the spell; invoking the menu is enough to produce the effect. This also happened when I manually implemented this with Disch's Disassembly.

<b>Additional observations:</b>
Furthermore, I noticed this behavior, picking up from after step 3) of the previous steps:
4) with that same character, select MAGIC again, but this time immediately cancel with B while the L1-4 page is showing;
5) with the same character, select FIGHT, pick an enemy, press A;
-> the attack lands, the game DOES NOT freeze, combat continues normally.

Just DISPLAYING the L5-8 page freezes after physical attacks or running, but display the L1-4 page again will prevent the freeze from occurring.

Technical details:
I used FCEUX to debug the game and discovered that it's entering an infinite loop while attempting to display a battle message. Using Disch's Disassembly as a reference, this is what I found:
The loop is in the DrawBattleString routine, bank 0F at $F9AB (ROM address 0x3F9BB).
The loop happens between bank addresses $F9D6 and F9E0 (at the @BottomLoop label in bank_0F.asm).
The loop is trying to draw the battle row of tiles of an interleaved null terminate string of tiles, stored in the buffer btl_stringoutputbuf starting $6CD4+1).
The loop can't end because the buffer is filled with space tiles (value $FF), not null tiles ($00), so the BEQ $F9F3 test fails (the Z flag is never set).

I'm not quite sure what's causing it, my conjecture is that moving the turn selection to occur when the character's turn order happens is allowing one or more variables to retain the wrong value, and that in turn is messing with the routines that undraw and redraw the message boxes. The L1-4 spell correcting it points to a possible difference in registers, the stack, temporary memory, something that isn't happening when changing to the L5-8 page.

I'm now examining the routine that handles the magic pages, BattleSubMenu_Magic at bank 0C:$94F5 (ROM address 0x31505).

That's a guess though, I've been at it for 2 weeks now, that's as far as I've gotten.

If anyone has any additional info, please post it to this thread (or link to this one). Hopefully one (or more) of us can crack the code on this one, because I absolutely love the way this patch makes the game flow!
If I find anything else on this, I'll update this thread.

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #1 on: August 29, 2016, 03:14:41 am »
Interesting!

It's too late for me to dig into this tonight (currently after midnight by me -- I really need to go to sleep).   But I'll try to put some time in it tomorrow.   :beer:

August 29, 2016, 11:56:39 am - (Auto Merged - Double Posts are not allowed before 7 days.)
The problem is triggered in RespondDelay_ClearCombatBoxes (bank C).  This routine "undraws" all the boxes that display combat information.  It uses a variable 'btl_combatboxcount' ($6AF8) to know how many boxes to undraw.  This variable is incremented when a new box is drawn and decremented when one is cleared.

When the game is crashing, this value is 1 higher than it should be, resulting in a non-existent box being undrawn, which wipes a HUGE chunk of memory, resulting in a crash shortly after.

The reason the value is 1 higher than it should be is because 6AF8 is also used as a temporary variable to hold the page number for the magic submenu.  So if you leave the magic submenu on page 1 (showing L5-L8 spells), it leaves a '1' in that var rather than the expected '0'.

This isn't a problem in the original game because this value is wiped in the main battle loop before all these boxes are drawn.



Possible solution:  Change the magic submenu to use a different space for temp RAM.  Anything in the math buffer should be safe to use (ie:  6856 would probably work)

I'll try making this change and see if it fixes the problem.  Will report back shortly



=======================
EDIT:
=======================

Yep.  That fixes it.

Patch here:

https://www.dropbox.com/s/0hvi55i9h21p82t/FinalFantasy_dynamic_battle_fix.ips?dl=0


This is not the full patch -- this is just the changes I made to the dynamic action patch.  So you would apply this patch on top of that one.

Might interfere with some other patches -- namely GFF or any other patch that modifies the way menus are drawn.

Shouldn't break savestates or save games.  So if you hit this freeze in your game you can apply this patch, reload the ROM & state and you'll be good to go.
« Last Edit: August 29, 2016, 12:14:16 pm by Disch »

essellejaye

  • Jr. Member
  • **
  • Posts: 27
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #2 on: August 29, 2016, 01:29:59 pm »
Thanks, Disch, you are the man!  :thumbsup:

I made a corresponding assembly change in line with your comment about the memory stomping problem with btl_combatboxcount and the magic page number both using $6AF8. So far, moving it to $6856 (btl_mathbuf) is working, I haven't noticed any problems with I - I've been blasting enemies with FIR3 and using CUR3 and HEL3 for the last 15 minutes, so it seems to work.

Thanks again, I'm betting you just made a lot of FF1 hackers VERY happy  :laugh:

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #3 on: August 29, 2016, 04:52:52 pm »
NP, but don't sell yourself short.  You did half the work.  Finding a reliable reproduction case is often harder than fixing the actual problem.   :thumbsup:

daman.tm

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #4 on: September 03, 2016, 11:53:57 am »
what changes would be needed to make this compatible with Grond's Final Fantasy? it works till one of the partymembers die, then it freezes

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #5 on: September 04, 2016, 03:32:57 am »
I have little knowledge (and little want to gain knowledge) about GFF.

Does the same "works until someone dies" problem exist with the normal patch?  If yes, I'll look into it.  If not, GFF probably moved a routine around for space and is therefore incompatible with my patch.

daman.tm

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #6 on: September 04, 2016, 06:58:18 am »
Alright, I tested the following things:

base rom: Final Fantasy(U)[!].nes
patches: Dynamic Action patch, Unofficial update patch, Dynamic battle fix (your patch)

I tried the following combos:

1) Base rom + Dynamic Patch + battle fix:
It works, only weird thing is that the dead party member still gets a turn, but his turn ends instantly.

2) Base rom + Dynamic Patch + Unofficial update + battle fix
Also works, and the unofficial update gets rid of the redundant back and forth walking at the start of a turn.

kinda a shame this new dynamic way of fighting isn't compatible with hacks that remodel the battle screen. Hope Grond reads all this, maybe he'll make an updated patch :P

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #7 on: September 04, 2016, 09:43:59 am »
If Grond releases his modified disassembly I'd be more interested in looking at it.  But as it is now I already disassembled the ROM once and don't want to disassemble it again.    :P

daman.tm

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #8 on: September 04, 2016, 12:36:50 pm »
Any handy way to contact Grond? I don't know if he has a website or if he reads his pm's on this forum.

EDIT: sent a pm to Grond, really hope we'll get an update for Grond's Final Fantasy
« Last Edit: September 04, 2016, 12:42:04 pm by daman.tm »

Duke2go

  • Full Member
  • ***
  • Posts: 192
    • View Profile
    • Final Fantasy Reconstructed
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #9 on: November 01, 2016, 10:55:11 pm »
I have little knowledge (and little want to gain knowledge) about GFF.

Does the same "works until someone dies" problem exist with the normal patch?  If yes, I'll look into it.  If not, GFF probably moved a routine around for space and is therefore incompatible with my patch.

Don't ever sell yourself short old friend. NEVER that!!  :beer:

Any handy way to contact Grond? I don't know if he has a website or if he reads his pm's on this forum.

EDIT: sent a pm to Grond, really hope we'll get an update for Grond's Final Fantasy

I tried to contact him when I first started the Final Fantasy Reconstructed project about a year or 2 ago and never heard back. I was really interested in talking to him and getting some insight.

You are all awesome for fixing this!!! Thank you from the very bottom of my heart!!  :thumbsup: :laugh: ;D ;) :laugh: :happy:
Tell my tale to those who ask. Tell it truly, the ill deeds along with the good, and let me be judged accordingly. The rest... is silence...

http://www.ffreconstructed.com/
https://www.facebook.com/finalfantasyreconstructed/

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #10 on: November 03, 2016, 11:19:55 am »
Don't ever sell yourself short old friend. NEVER that!!  :beer:

Hahaha.  I'm not.  I mean I'm sure I could do it, I just have no interest in attempting.  :crazy:

Duke2go

  • Full Member
  • ***
  • Posts: 192
    • View Profile
    • Final Fantasy Reconstructed
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #11 on: November 04, 2016, 01:06:02 am »
Hahaha.  I'm not.  I mean I'm sure I could do it, I just have no interest in attempting.  :crazy:

I feel you there. The fix seems to hold perfectly with the existing Reconstructed rom image, and I'm working through a playthrough now to make sure everything is perfect. You know I'll be including you for a special thank you in the credits of the official release for you and essellejaye for your work on this, and all the help you've given me in the past. This awesome improvement is just another feather in your cap. The only thing I've noticed that's a bit peculiar is that a player character can actually sometimes take 2 turns in a row. It mostly happens with my Thief (since I've always got 1 of those in whatever party). Didn't remember adding any agility to him, but I could be wrong. Don't know if anybody else found that while playing. God bless you and yours bro.

 :angel:
« Last Edit: November 05, 2016, 02:21:03 am by Duke2go »
Tell my tale to those who ask. Tell it truly, the ill deeds along with the good, and let me be judged accordingly. The rest... is silence...

http://www.ffreconstructed.com/
https://www.facebook.com/finalfantasyreconstructed/

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #12 on: November 04, 2016, 12:42:15 pm »
The only thing I've noticed that's a bit peculiar is that a player character can actually sometimes take 2 turns in a row. It mostly happens with my Thief (since I've always got 1 of those in whatever party). Didn't remember adding any agility to him, but I could be wrong. Don't know if anybody else found that while playing. God bless you and yours bro.

This could be just the way the RNG is setting up the turns.

If your thief goes last one round, then first the next round, he'll get 2 back-to-back turns (but never 3)

Example:  5 entities per round (A-E), let's say your Thief is 'E'

Round 1: BDCAE
Round 2: EACBD


'E' goes 5th and 6th

essellejaye

  • Jr. Member
  • **
  • Posts: 27
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #13 on: November 04, 2016, 08:32:03 pm »
Since this patch makes the characters take their turns immediately, there's not a clear, discernable indicator that one round has ended and the next round has begun.

At least on FCEUX, there's a delay of a few frames (when the turn order is recalculated) that tips off the start of a new round, but that could just be how it runs on my system.

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #14 on: November 04, 2016, 09:21:56 pm »
but that could just be how it runs on my system.

Not likely.  NES emulators are pretty stable across systems.  Unless FCEUX has a weird history of inserting random pauses in games for you.

Duke2go

  • Full Member
  • ***
  • Posts: 192
    • View Profile
    • Final Fantasy Reconstructed
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #15 on: November 05, 2016, 02:23:48 am »
Since this patch makes the characters take their turns immediately, there's not a clear, discernable indicator that one round has ended and the next round has begun.

At least on FCEUX, there's a delay of a few frames (when the turn order is recalculated) that tips off the start of a new round, but that could just be how it runs on my system.

Seriously dude, top notch job working with the ATB patches to get them working correctly. I had specifically thanked you within my Reconstructed thread, but I didn't think I had done so here. If you're interested in any coding for that project I could certainly use the help. Thank you though for helping to fix the issues with Captain Muscles and Grond's patches. I was ecstatic to be able to re-introduce ATB to my project and I can't thank you and Disch enough  :thumbsup: :beer: :thumbsup:

November 12, 2016, 12:32:40 am - (Auto Merged - Double Posts are not allowed before 7 days.)
Since I was thinking of a way to actually do a video of my own for my project, I thought I might get some exposure for this thread and the work y'all have put in too if that's ok. I basically did a less than 2 minute vid of the current version of my Earth Cave to show some in-game vid of that location (which I'm really proud of), and how the ATB patches functioned.  I was going to put it on the project's YouTube and Facebook page. However, while I wanted to let more people know that the patches existed, I didn't want to draw any unwanted attention over here. If its ok with those involved, I'm gonna put a link to the thread at the end of the video and in the description to direct people to be able to access and use the patches. If y'all would rather I didn't include that info, does anyone have any problems with me putting up just the video that shows the working ATB in FF1? I've been reminded recently of the need to respect the feelings of others, and the people involved in this thread have been good to me since I started my project, so your opinions actually do matter.  So thank you for any input on preferences.

:beer:
« Last Edit: November 12, 2016, 12:32:40 am by Duke2go »
Tell my tale to those who ask. Tell it truly, the ill deeds along with the good, and let me be judged accordingly. The rest... is silence...

http://www.ffreconstructed.com/
https://www.facebook.com/finalfantasyreconstructed/

Vanya

  • Hero Member
  • *****
  • Posts: 1216
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #16 on: January 17, 2018, 02:28:30 am »
I want to confirm that there is an issue with using these patches over Grond's Final Fantasy.
There is good news and bad news.

Bad news is that there is definitely something not quite right as there is a bug that triggers when a party member is dead.

Good news is that it is a fairly minor bug.

As to the actual bug, it appears that when at least 1 party member is dead, the last party member who had their turn steps backward each time an enemy's text box is erased. This is actually kind of amusing to watch as each of your characters inches away from the enemy party until they eventually wrap back around the left side of the screen.

Hopefully this bug is fairly easy to squash as DAB + GFF is pretty damn cool.

January 17, 2018, 05:11:26 pm - (Auto Merged - Double Posts are not allowed before 7 days.)
On a side note, I'm thinking it might be a good idea to rewrite the whole turn order routine.
Since there are no more discrete rounds, it might be better to do something like the initiative rules from D&D and Pathfinder.
It could also be an opportunity to give agility an additional function.

Maybe something like this:
 Assign each character a number: random(0...24) + [AGI/4]
 Then set the turn order based on the assigned numbers.
 In case of a tie, the character with the higher AGI score goes first.
« Last Edit: January 17, 2018, 05:11:26 pm by Vanya »

Disch

  • Hero Member
  • *****
  • Posts: 2597
  • NES Junkie
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #17 on: January 17, 2018, 10:43:40 pm »
Quote
Maybe something like this:
 Assign each character a number: random(0...24) + [AGI/4]
 Then set the turn order based on the assigned numbers.
 In case of a tie, the character with the higher AGI score goes first.

Do a gauge.  Keep increasing by something like AGI+rand(0,Luck/2) or something like that, and once it reaches X they get a turn.  That'll nerf the extremely overpowered Fighter a bit because he won't get as many turns, and it'll give the player an actual reason to use a Thief --- maybe they don't hit as hard, but they get to hit way more often.

Enemies already have an agility stat, too, but it'll probably have to take some adjustment so that they match level-appropriate characters.  Actually, this whole plan would require some rebalancing, so maybe it's beyond the scope of what you want to do, but it would be my approach to this.

Vanya

  • Hero Member
  • *****
  • Posts: 1216
    • View Profile
Re: Debugging the Final Fantasy 1 Dynamic Action patch
« Reply #18 on: January 18, 2018, 03:35:48 am »
That's a good idea, and actually seems simpler to execute, too.
Yeah, definitely would require rebalancing. The lowly Goblin is granted a mere AGI 6.
I'd be up for trying to make the thing itself, but I would probably leave it to others to rebalance.


Edit:

I tested some averaged out number by hand and came up with this:

Pseudo-codeā€¦

According to the turn order improvement proposed by Anomie, the game already keeps an array of the 13 possible units in each battle. Presumably it also knows if a unit is present or not. By default the list of units is in this order: enemy unit 1-9, then PC unit 1-4.

How about something like this...
  RAM Usage
 - each unit has a 2 byte word for its gauge initialized to 00.
 - 2 bytes used as flags to track which units have had their turn.
   (That totals 28 bytes of free RAM needed.)

    Start Routine
   1- load gauge value of unit in array position X.
   2- If unit is not present, jump to line 27.
   3- If unit is petrified or dead, jump to line 27.
   4- If unit's turn flag is set, jump to line 29.
   5- If unit is PC, jump to 16.

    Enemy Stuff
   6- Save Unit's speed to a temp variable, speed = AGI/2 + Magic Defense/20.
   7- If unit is not slowed, jump to 10.
   8- Add speed/2 to unit's gauge.
   9- Jump to 14.
  10- If unit is not hasted, jump to 13.
  11- Add speed*2 to unit's gauge.
  12- Jump to 14.
  13- Add speed to unit's gauge.
  14- Add speed bonus to unit's gauge, speed bonus = Morale-100/5.
  15- Jump to 25.

    PC Stuff
  16- Save Unit's speed to a temp variable, speed = AGI/2 + INT/5.
  17- If unit is not slowed, jump to 20.
  18- Add speed/2 to unit's gauge.
  19- Jump to 14.
  20- If unit is not hasted, jump to 23.
  21- Add speed*2 to unit's gauge.
  22- Jump to 14.
  23- Add speed to unit's gauge.
  24- Add speed bonus to unit's gauge, speed bonus = Luck/2.

    End Routine
  25- If unit's gauge is less than 127, jump to 29.
  26- Set current unit to take it's turn, and jump to turn code.
  27- Set unit's turn flag.
  28- Set unit's gauge to 00.
  29- If not all turn flags are set, jump to line 31.
  30- Clear all turn flags.
  31- Increment array position by 1.
  32- Jump back to line 1.

This could be more streamlined, but I can't spend any more time on it today.
« Last Edit: January 18, 2018, 12:05:51 pm by Vanya »