lushen124 Report post Posted May 8, 2021 I figure I'd drop this here in case anybody needs it, since I was looking through FE4 ASM earlier for the Yune randomizer. Maybe it's already out there and I just didn't look hard enough. Removing the Pursuit requirement for follow-up attacks All ROM addresses are headered and based off of the original (though I've tested it with the Naga patch). 0x4E567 Old Values: 90 12 BD 24 00 89 00 40 F0 0A B9 30 00 DD 30 00 10 02 38 60 18 60 New Values (the 00s don't matter, I just stubbed them out so that it's clear they do nothing) 20 10 FF 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x50110 Old Values: All 00s. New Values: 90 2C B9 30 00 DD 30 00 10 24 BD 24 00 89 00 40 F0 0E BD 30 00 38 F9 30 00 C9 03 00 90 10 80 0C BD 30 00 38 F9 30 00 C9 06 00 90 02 38 60 18 60 In that set of new values, there are two values that can be tweaked. The two 0xC9 bytes are each followed by a value for the AS threshold needed to double with and without Pursuit. In the above example, this is 6 AS to double without Pursuit and 3 AS to double with Pursuit. Technical Explanation The first change replaces the routine that checks for Pursuit to determine doubling. Originally, this ASM looked like this: $84/E367 90 12 BCC $12 [$E37B] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Some kind of check that bypasses this entire sequence if the result of the previous function (see above) has the carry flag cleared. $84/E369 BD 24 00 LDA $0024,x[$7E:4ED9] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Loads Attacker Skills into Accumulator. $84/E36C 89 00 40 BIT #$4000 A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Check if the Pursuit bit is set. If it is, clears the zero flag. $84/E36F F0 0A BEQ $0A [$E37B] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Branches if zero flag was set. $84/E371 B9 30 00 LDA $0030,y[$7E:4F45] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Loads the defender's AS into the Accumulator $84/E374 DD 30 00 CMP $0030,x[$7E:4EE5] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Compares it with the attacker's AS. Sets the negative flag if necessary (i.e. Defender AS - Attacker AS) $84/E377 10 02 BPL $02 [$E37B] A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Branches to skip the double attack if the negative flag was not set. (i.e. Defender AS > Attacker AS) $84/E379 38 SEC A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Sets the Carry to indicate a follow up attack is needed. $84/E37A 60 RTS A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Return $84/E37B 18 CLC A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- The Branch Destination if there is no double attack. Clears the Carry flag to indicate no double attack. $84/E37C 60 RTS A:0000 X:4EB5 Y:4F15 P:envmxdizc <-- Return Since the check is bit more complex, I opted to jump to my own subroutine and do calculations there for more space. Thankfully Jump and Return instructions don't mess with any flags, which is what we need to preserve for returning to the original caller. The ASM for the jump is just: $84/E367 20 10 FF JSR $FF10 [$84:FF10] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Jump to our new subroutine. $84/E36A 60 RTS A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Return the result from our new subroutine. $84/E36B 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Stubbed out to 00s. $84/E36D 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E36F 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E371 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E373 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E375 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E377 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E379 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/E37B 00 00 BRK #$00 A:0000 X:4EB5 Y:4F15 P:envmxdiZC The new code we wrote is in the same data bank, but uses empty space at the end of the bank. The ASM looks like this: $84/FF10 90 2C BCC $2C [$FF3E] A:0000 X:4EB5 Y:4F15 P:envmxdiZC $84/FF12 B9 30 00 LDA $0030,y[$7E:4F45] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Loads the defender's AS. $84/FF15 DD 30 00 CMP $0030,x[$7E:4EE5] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Compares the defender AS with the attacker AS. $84/FF18 10 24 BPL $24 [$FF3E] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If the defender is faster, skip the rest and return no follow-up. $84/FF1A BD 24 00 LDA $0024,x[$7E:4ED9] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Load the attacker's skills. $84/FF1D 89 00 40 BIT #$4000 A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Does the attacker have Pursuit? $84/FF20 F0 0E BEQ $0E [$FF30] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If he doesn't, skip to the logic for checking doubling threshold without Pursuit. $84/FF22 BD 30 00 LDA $0030,x[$7E:4EE5] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If we get here, the attacker has Pursuit. Load the attacker AS. $84/FF25 38 SEC A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- 65816 CPU quirk for subtraction. $84/FF26 F9 30 00 SBC $0030,y[$7E:4F45] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Subtract the defender's AS from the attacker's. $84/FF29 C9 03 00 CMP #$0003 A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Compare it to the Pursuit threshold (3 in this case). Sets the carry flag if AS difference > threshold. $84/FF2C 90 10 BCC $10 [$FF3E] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If carry flag is not set, skip to the end. No follow-up needed. $84/FF2E 80 0C BRA $0C [$FF3C] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Otherwise, we have a follow-up. Always jump to the follow-up routine. $84/FF30 BD 30 00 LDA $0030,x[$7E:4EE5] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If we get here, the attacker does not have Pursuit. Same as above, load the attacker AS. $84/FF33 38 SEC A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- 65816 CPU quirk for subtraction. $84/FF34 F9 30 00 SBC $0030,y[$7E:4F45] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Subtract the defender's AS from the attacker's. $84/FF37 C9 06 00 CMP #$0006 A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Compare it to the non-Pursuit threshold (6 in this case). Sets the carry flag if AS difference > threshold. $84/FF3A 90 02 BCC $02 [$FF3E] A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If carry flag is not set, skip to the end. No follow-up needed. $84/FF3C 38 SEC A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If we get here, we have a follow-up attack. Set the carry flag to indicate this. $84/FF3D 60 RTS A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Return. $84/FF3E 18 CLC A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- If we get here, we don't have a follow-up attack. Clear the carry flag to indicate this. $84/FF3F 60 RTS A:0000 X:4EB5 Y:4F15 P:envmxdiZC <-- Return. Note: I use "Attacker" and "Defender", but that really just refers to the values in the X and Y registers. The routine is called twice if necessary, swapping X and Y in the second case. I suspect this only happens if the initial call does not result in a follow-up attack, since only one side can have a follow-up. Quote Share this post Link to post Share on other sites
Camus The Dark Knight Report post Posted June 6, 2021 (edited) On 4/14/2021 at 12:35 AM, windypanda1 said: I had to do hecking 2 hours of digging around the Char Portrait Editor to find the Young Arvis Sprite. Here are some pointers I've recorded to save others some trouble. 89 00 = Old Arvis 8A 00 = Julius 8C 00 = Ishtar 56 00 = Eltshan 5D 00 = Langobalt 51 = Andrey 52 = Blume 53 = Dannan 54 = Lamia 55 = Arvis 5A = Dithorba 5B = Mahnya 59 = Pamela 5C = Donovan 54 = Hilda 9B = Slayder Know it's an old post, but to save anyone else time in the future here is a complete visual list of all the portraits in the game and their pointers. I didn't make it, just consolidated them, whoever made it seems to have ordered them by family. I just added the generic portraits to complete it. (Oddly a FE3 one makes it in, the only FE3 hold over I have found in FE4) https://imgur.com/a/0Gg4aHi Edited June 6, 2021 by Camus The Dark Knight Quote Share this post Link to post Share on other sites
Slig Report post Posted March 5 Is it possible to make it so that weapons never gain crit regardless of the number of kills? Quote Share this post Link to post Share on other sites