News:

11 March 2016 - Forum Rules

Main Menu

Final Fantasy II Restored

Started by redmagejoe, December 10, 2019, 03:09:14 AM

Previous topic - Next topic

Leviathan Mist

Quote from: BlazeHeatnix on January 31, 2020, 01:14:10 AM
I don't know if it's been mentioned in this thread, but here's a possible inclusion for a Restored-esque update to the game: more music. The Origins-exclusive extra boss themes could be added to the game, adding the extra sections to the Prelude or Chocobo theme (it desperately needs it), or perhaps even the unused music that Uematsu wrote but ultimately discarded.

https://youtu.be/Xj7a91dlI4c?t=1379

Thank you for posting this. I had completely forgotten about the unused music for this game. Now the question remains: does the music data in raw format exist online? If not, then it would be up to me to interpret it and code by ear. I would imagine it would sound a lot closer to the source material than did my FF1 tracks, as it would use the same sound engine.

BlazeHeatnix

Quote from: Leviathan Mist on January 31, 2020, 11:05:46 AM
Thank you for posting this. I had completely forgotten about the unused music for this game. Now the question remains: does the music data in raw format exist online? If not, then it would be up to me to interpret it and code by ear. I would imagine it would sound a lot closer to the source material than did my FF1 tracks, as it would use the same sound engine.

Unfortunately, I don't think it exists in raw format. It was only released on the soundtrack in 1988. Tracking this down to listen to the tracks in anything other than compressed Youtube quality might be difficult.
https://finalfantasy.fandom.com/wiki/Original_soundtracks_of_Final_Fantasy_I_%26_II#All_Sounds_of_Final_Fantasy_I_.26_II

Even if these are transcribed...what would you do with them? These were cut out for creative reasons, not technical ones. Also, where would you put the Dungeon theme seeing as there already is a dungeon theme in the game? Would it go in some dungeons but not others? And I assume Battle Scene 3 would be reserved for the final boss.

redmagejoe

As I stated in my previous post, I feel like the current boss theme is the most appropriate for the final boss, especially considering how it was used in remakes. I wouldn't honestly use any of the others besides perhaps Battle Scene 3, which I'd feel would fit appropriately as a one-time use for the Behemoth fight in Coliseum. Were it feasible to fit a demake of Battle Scene A in the ROM, I'd like to use that for bosses, and use the current boss theme exclusively for the final boss.

BlazeHeatnix

#183
Quote from: redmagejoe on January 31, 2020, 03:11:32 PM
As I stated in my previous post, I feel like the current boss theme is the most appropriate for the final boss, especially considering how it was used in remakes. I wouldn't honestly use any of the others besides perhaps Battle Scene 3, which I'd feel would fit appropriately as a one-time use for the Behemoth fight in Coliseum. Were it feasible to fit a demake of Battle Scene A in the ROM, I'd like to use that for bosses, and use the current boss theme exclusively for the final boss.

I personally have an issue with using any tracks not originally composed by Uematsu, as they sound sorely out of place in Origins. As Battle Scene 2 has become synonymous with the Emperor over the years, I sort of understand wanting to use it for the final boss, but I still think Battle Scene 3 is too sinister and too long to be used in only one throwaway fight. I would recommend using it for the very first fight against Mateus as a human, as it's a way to fool the player into thinking "This is it! The final boss!" before the actual final boss happens. (Personally I'd use Scene 2 for the human fight and Scene 3 for the final boss since I don't think Scene 2 sounds like a proper final boss theme, but I get how that'd be alienating to some people so I won't argue for it.)

It might sound like a waste of time, a lot of work, and something you understandably don't want to think about before all the bugs are fixed, but it would make sense to me to offer players the choice of whether they want the original soundtrack, the unused soundtrack, an Origins-style soundtrack, or a custom soundtrack chosen by you, RMJ, which would be the default, and all except the original would have an improved Prelude and Chocobo theme.

redmagejoe

It comes down to feasibility of inclusion more than anything. My default is to simply have none of the battle music changed at this moment, because until the code is cleaned up and we start looking at space, the only thing I'd like to see done is the Prelude given its 80-byte treatment. If I were to explore optional patch setups, I would do so only after I saw what could and could not fit into the space available, and that only if Leviathan Mist were willing to put the time and energy into those tracks in the first place.

There's a lot to be said for the creative reasons behind not using certain tracks, so whether Uematsu made Battle Scene 3 or didn't make Battle Scene A should have just as much impact on the final decision about what setups to use as the very valid argument that changing the final boss theme could be alienating to people who played the original and associate that theme with the final boss more than any of the other bosses in the game.

When all is said and done, I'll worry about what battles use what songs in what optional patch setups if and when the two tracks in question even exist, let alone fit in 256kb. At the end of the day, I'm not going to make a unilateral choice or take creative liberties over what should or shouldn't be changed outside of bug fixes. I didn't like that Astral Esper did that with the Peninsula of Power and shop lists in Restored (that's why I made the Final Fantasy Restored Debalance patch!), and I'm not about to do that here. The Mysidian Orbs change, for instance, will likely be a separate IPS included as an optional addition.

Leviathan Mist

Quote from: BlazeHeatnix on January 31, 2020, 03:43:59 PM
I personally have an issue with using any tracks not originally composed by Uematsu, as they sound sorely out of place in Origins. As Battle Scene 2 has become synonymous with the Emperor over the years, I sort of understand wanting to use it for the final boss, but I still think Battle Scene 3 is too sinister and too long to be used in only one throwaway fight. I would recommend using it for the very first fight against Mateus as a human, as it's a way to fool the player into thinking "This is it! The final boss!" before the actual final boss happens. (Personally I'd use Scene 2 for the human fight and Scene 3 for the final boss since I don't think Scene 2 sounds like a proper final boss theme, but I get how that'd be alienating to some people so I won't argue for it.)

It might sound like a waste of time, a lot of work, and something you understandably don't want to think about before all the bugs are fixed, but it would make sense to me to offer players the choice of whether they want the original soundtrack, the unused soundtrack, an Origins-style soundtrack, or a custom soundtrack chosen by you, RMJ, which would be the default, and all except the original would have an improved Prelude and Chocobo theme.

I have read your review of Final Fantasy Restored, and I appreciate your honest input about the new tracks. I originally created them as a proof-of-concept while playtesting AstralEsper's other hack, Final Fantasy Rebalanced. Since there were no true 8-bit renditions of the tracks (not counting the Wonderswan Color versions), I had to take some liberties for some of the tunes, and add my own personal flair to some of them to prevent them from sounding stale. I do agree that the music patches should be optional though.

As for FF2, I'm waiting for more space to be freed up, and a confirmation that the space can be properly utilized for music, before I dig into the FF2 sound engine. I will have to analyze it myself to see if I can make sense of it, hoping it's not too different from the way FF1's sound engine was written. If that part goes smoothly, I will start my first test track, and then post a NSF file for feedback. Maybe you could post a poll asking which new track to work on first, when the time comes.

Heaven Piercing Man

Also take into account that FF2j has a completely different distribution of the boss theme than the remakes. The boss theme is used for the first time against Behemoth, and then here and there including the final boss and EXCLUDING the Human Mateus fight.

The remakes use only Battle Scene B as the only boss theme at first, then Battle Scene A is used for the first time against Lamia Queen, then it depends on the boss (the very next boss, Behemoth, uses type B)

Leviathan Mist

I just took a quick look at the FF2 NSF file. Looks like a completely different system. Which means it would take some time to decode everything. I wouldn't hold my breath on a timely release of any ported songs.

BlazeHeatnix

Quote from: Leviathan Mist on February 01, 2020, 09:32:24 AM
I just took a quick look at the FF2 NSF file. Looks like a completely different system. Which means it would take some time to decode everything. I wouldn't hold my breath on a timely release of any ported songs.


redmagejoe

#189
Just an update that I've had my hands full with work, but I'll be coming back to this soon. I'd kind of like to get abw's insight on all the new information as well before I charge ahead, as he seems to have a better grasp of what's happening than I do in code, and I have a tendency to trial-and-error stumble my way through things. :P

Based on the poll, I've decided to make an optional patch that gives all 4 characters the stat boosts. I just need to find the space for an LD*, an IN*, a CMP/CPX/CPY, and a BNE. So about 7-8 bytes.


; handler for bottom left orb, Fire Crystal
; indirect control flow target (via $99A5)
0x03A1BF|$0E:$A1AF:A9 10    LDA #$10    ; Stat offset for base Strength
0x03A1C1|$0E:$A1B1:D0 0A    BNE $A1BD
; handler for bottom right orb, Wind Crystal
; indirect control flow target (via $99A7)
0x03A1C3|$0E:$A1B3:A9 11    LDA #$11    ; Stat offset for base Agility
0x03A1C5|$0E:$A1B5:D0 06    BNE $A1BD
; handler for top left orb, Earth Crystal
; indirect control flow target (via $99A9)
0x03A1C7|$0E:$A1B7:A9 14    LDA #$14    ; Stat offset for base Spirit
0x03A1C9|$0E:$A1B9:D0 02    BNE $A1BD
; handler for top right orb, Water Crystal
; indirect control flow target (via $99AB)
0x03A1CB|$0E:$A1BB:A9 13    LDA #$13    ; Stat offset for base Intellect
; control flow target (from $A1B1, $A1B5, $A1B9)
0x03A1CD|$0E:$A1BD:85 80    STA $80    ; store offset in $80 based on which orb and thus stat is being increased
0x03A1CF|$0E:$A1BF:A5 F0    LDA $F0    ; load A with whatever's in $F0 (RNG output to determine character?)
0x03A1D1|$0E:$A1C1:29 C0    AND #$C0    ; bitwise AND against $F0 (???? ????) with #$C0 (1100 0000)
0x03A1D3|$0E:$A1C3:05 80    ORA $80    ; bitwise OR with resultant A value from AND above against $80 (stat offset $10, $11, $13, or $14)
0x03A1D5|$0E:$A1C5:AA      TAX        ; store this A value in X to be used as the determined offset for which character gets the bonus
0x03A1D6|$0E:$A1C6:BD 00 61 LDA $6100,X ; Character #1 ID/portrait/sprite (00: Firion, 01: Maria, 02: Guy, 03: Minwu, 04: Josef, 05: Gordon, 06: Leila, 07: Ricard, 08: Leon); load A with baseline for character stats, X as offset
0x03A1D9|$0E:$A1C9:18      CLC
0x03A1DA|$0E:$A1CA:69 0A    ADC #$0A    ; adds 10 to the appropriate stat
0x03A1DC|$0E:$A1CC:C9 64    CMP #$64    ; prevent stat from going above 99, compare to 100
0x03A1DE|$0E:$A1CE:90 02    BCC $A1D2  ; does not exceed cap, proceed to store new stat value
0x03A1E0|$0E:$A1D0:A9 63    LDA #$63    ; set stat to 99 if >99
; control flow target (from $A1CE)
0x03A1E2|$0E:$A1D2:9D 00 61 STA $6100,X ; Character #1 ID/portrait/sprite (00: Firion, 01: Maria, 02: Guy, 03: Minwu, 04: Josef, 05: Gordon, 06: Leila, 07: Ricard, 08: Leon); store new value of stat, baseline for character stats, X as offset
0x03A1E5|$0E:$A1D5:BD 10 61 LDA $6110,X ; Character #1 Base Strength; base character stats that display in stat window (base + equipment bonuses), X as offset
0x03A1E8|$0E:$A1D8:18      CLC
0x03A1E9|$0E:$A1D9:69 0A    ADC #$0A    ; add 10 to window stats as well
0x03A1EB|$0E:$A1DB:C9 64    CMP #$64    ; prevent stat from going above 99, compare to 100
0x03A1ED|$0E:$A1DD:90 02    BCC $A1E1  ; does not exceed cap, proceed to store new stat value
0x03A1EF|$0E:$A1DF:A9 63    LDA #$63    ; set stat to 99 if >99
; control flow target (from $A1DD)
0x03A1F1|$0E:$A1E1:9D 10 61 STA $6110,X ; Character #1 Base Strength; store new value of stat, baseline for character's window stats, X as offset
0x03A1F4|$0E:$A1E4:A4 A0    LDY $A0
0x03A1F6|$0E:$A1E6:20 07 99 JSR $9907
0x03A1F9|$0E:$A1E9:AD 00 7B LDA $7B00
0x03A1FC|$0E:$A1EC:60      RTS



; handler for bottom left orb, Fire Crystal
; indirect control flow target (via $99A5)
0x03A1BF|$0E:$A1AF:A9 10    LDA #$10    ; Stat offset for base Strength
0x03A1C1|$0E:$A1B1:D0 0A    BNE $A1BD
; handler for bottom right orb, Wind Crystal
; indirect control flow target (via $99A7)
0x03A1C3|$0E:$A1B3:A9 11    LDA #$11    ; Stat offset for base Agility
0x03A1C5|$0E:$A1B5:D0 06    BNE $A1BD
; handler for top left orb, Earth Crystal
; indirect control flow target (via $99A9)
0x03A1C7|$0E:$A1B7:A9 14    LDA #$14    ; Stat offset for base Spirit
0x03A1C9|$0E:$A1B9:D0 02    BNE $A1BD
; handler for top right orb, Water Crystal
; indirect control flow target (via $99AB)
0x03A1CB|$0E:$A1BB:A9 13    LDA #$13    ; Stat offset for base Intellect
; control flow target (from $A1B1, $A1B5, $A1B9)
0x03A1CD|$0E:$A1BD:AA    TAX             <<<
0x03A1CE|$0E:$A1BE:BD 00 61 LDA $6100,X ; Character #1 ID/portrait/sprite (00: Firion, 01: Maria, 02: Guy, 03: Minwu, 04: Josef, 05: Gordon, 06: Leila, 07: Ricard, 08: Leon); load A with baseline for character stats, X as offset
0x03A1D1|$0E:$A1C1:18      CLC
0x03A1D2|$0E:$A1C2:69 0A    ADC #$0A    ; adds 10 to the appropriate stat
0x03A1D4|$0E:$A1C4:C9 64    CMP #$64    ; prevent stat from going above 99, compare to 100
0x03A1D6|$0E:$A1C6:90 02    BCC $A1CA  ; does not exceed cap, proceed to store new stat value
0x03A1D8|$0E:$A1C8:A9 63    LDA #$63    ; set stat to 99 if >99
0x03A1DA|$0E:$A1CA:9D 00 61 STA $6100,X ; Character #1 ID/portrait/sprite (00: Firion, 01: Maria, 02: Guy, 03: Minwu, 04: Josef, 05: Gordon, 06: Leila, 07: Ricard, 08: Leon); store new value of stat, baseline for character stats, X as offset
0x03A1DD|$0E:$A1CD:BD 10 61 LDA $6110,X ; Character #1 Base Strength; base character stats that display in stat window (base + equipment bonuses), X as offset
0x03A1E0|$0E:$A1D0:18      CLC
0x03A1E1|$0E:$A1D1:69 0A    ADC #$0A    ; add 10 to window stats as well
0x03A1E3|$0E:$A1D3:C9 64    CMP #$64    ; prevent stat from going above 99, compare to 100
0x03A1E5|$0E:$A1D5:90 02    BCC $A1D9  ; does not exceed cap, proceed to store new stat value
0x03A1E7|$0E:$A1D7:A9 63    LDA #$63    ; set stat to 99 if >99
0x03A1E9|$0E:$A1D9:9D 10 61 STA $6110,X ; Character #1 Base Strength; store new value of stat, baseline for character's window stats, X as offset
0x03A1EC|$0E:$A1DC:8A      TXA             <<<
0x03A1ED|$0E:$A1DD:18      CLC             <<<
0x03A1EE|$0E:$A1DE:69 40  ADC #$40        <<<
0x03A1F0|$0E:$A1E0:90 DB  BCC $A1BD       <<<
0x03A1F2|$0E:$A1E2:A4 A0    LDY $A0
0x03A1F4|$0E:$A1E4:20 07 99 JSR $9907
0x03A1F7|$0E:$A1E7:AD 00 7B LDA $7B00
0x03A1FA|$0E:$A1EA:60      RTS
0x03A1FB|$0E:$A1EB:EA      NOP
0x03A1FC|$0E:$A1EC:EA      NOP


I need 3 more bytes to make this mock-up work. I had thought of not using LDY and INY originally, but I couldn't think of a consistent way to handle a CMP when the offset can vary between 0 and 4 (for the stat), so I decided to use Y as a counter. If anyone's more clever than me about how to use CMP to compare it against D0, D1, D3, or D4, I'm all ears (00 + 10/11/13/14 + 40x3 to cycle through the 4 characters). Nevermind, I figured it out. Since I have it doing the stat adjustment first, ADC for character offset last before the comparison, I should be able to make it work. 10-14, increase Firion's stat, increase offset to 50-54, compare, branch up to increase Maria's stat, increase offset to 90-94, compare, branch up to increase Guy's stat, increase offset to D0-D4, compare, branch up to increase Char4's stat, increase offset to... well, 0114, but that should set the carry flag... compare, break out of loop. So I should be able to do CMP #$D5 with a BCC so that after the 4th character, it will increment above D4 and break out of the loop. Unless the CMP breaks the carry flag being set, which may cause problems.

Could I remove the CMP altogether and achieve the same result? CLC is run before the ADC, so unless it's above FF, it should always branch, right? In the case where it increments from D0-D4 up to >FF, it should set the Carry Flag, and thus not branch, correct? Adjusted mock-up accordingly, as I'm pretty sure that should work.

Bregalad

Quote from: Leviathan Mist on February 01, 2020, 09:32:24 AM
I just took a quick look at the FF2 NSF file. Looks like a completely different system. Which means it would take some time to decode everything. I wouldn't hold my breath on a timely release of any ported songs.
I'm surprised you're surprised of this. You can hear it right away. FF1's sound engine is very limited, even compared to other 1987 NES games, while FF2 is much more featured. However FF3 sound engine sounds like an upgrade of FF2's. And other games such as Minna no Taabou no Nakayoshi Dai Sakusen, sounds the same as FF2 or FF3. I didn't look at any line of code to assert such a thing, though.

For the music my opinion is to not touch it, unless it is a bugfix. The remixes used in Danws of Souls are not by Uematsu. But also, it's part of history of the series that the Prelude and Chocobo theme were originally composed simpler as their later versions, and were expanded in FF4 and FF3 respectively. FF1 and FF2 not having boss themes (except for some bosses in FF2) is also part of the series.

redmagejoe

#191
Could use someone with a save state in the Ultima room to playtest the patch I may put up soon to ensure that it grants the bonus to all 4 characters, and doesn't break anything. Sadly, I don't have anything remotely close to that point (right after in fact is the earliest I have), and I'd really rather not try to play through the game all the way up to that point again...

Leviathan Mist

Quote from: redmagejoe on February 02, 2020, 05:15:53 PM
Could use someone with a save state in the Ultima room to playtest the patch I may put up soon to ensure that it grants the bonus to all 4 characters, and doesn't break anything. Sadly, I don't have anything remotely close to that point (right after in fact is the earliest I have), and I'd really rather not try to play through the game all the way up to that point again...

I would probably have one for you by now if you hadn't told me to hold off on my playthrough :P

redmagejoe

#193
I'd hate to have you streaming up to a point where it breaks though, unless you're okay with it being a proof-of-concept / playtesting stream. I'd feel awful if people were watching you and you got to the orbs, and then the game just crashed. :x

Having said that though, if you're not averse to playtesting, I think the patches that are up now are a pretty good start if you'd like to give it a whirl! First post has been updated with the "WIP" patch. All other patches should be good to go, but playtesting is always nice. If you are willing to collect Save States, I could use one for:

  • Before opening Kashuan Keep with the Goddess's Bell.
  • Before collecting the Sunfire from Kashuan Keep with Egil's Torch in hand.
  • Before stepping onto the Dreadnought and showing the Pass to the guard.
  • Before throwing the Sunfire into the Dreadnought's core.
  • Before placing White Mask on the Goddess Statue.
  • Before placing Black Mask on the frozen Doppelganger.
  • Before touching any of the orbs at the top of the Mysidian Tower.
  • Before speaking to Elina in Deist Castle one last time before she and her son vanish.

I looked through the disassembly and found at least one other instance where a BCC is used directly after an ADC, so I think I've got the right idea at least.




Upon further investigation, it seems like Protect at different levels and which target is chosen is completely buggy. Level 8 Protect (which should be 99/4 = 24 x # of successes based on spell level) is giving Guy 0 defense when cast on himself, and 24 ($18) to himself when cast on party. Spells may become more complicated than I'd initially thought.

Also it seems I was incorrect about that ADC #$14 being Ripper. Just adjusted the value to 00 and still displays # of hits x 20 over what Firion actually takes when he hits himself with Ripper. Going to have to think more critically about how to find this bug.


; control flow target (from $AF9A)
0x032FCD|$0C:$AFBD:A0 18    LDY #$18
0x032FCF|$0C:$AFBF:B1 9F    LDA ($9F),Y
0x032FD1|$0C:$AFC1:A0 07    LDY #$07
0x032FD3|$0C:$AFC3:18      CLC
0x032FD4|$0C:$AFC4:71 9F    ADC ($9F),Y
0x032FD6|$0C:$AFC6:85 46    STA $46
0x032FD8|$0C:$AFC8:A9 00    LDA #$00
0x032FDA|$0C:$AFCA:69 00    ADC #$00
0x032FDC|$0C:$AFCC:85 47    STA $47
0x032FDE|$0C:$AFCE:38      SEC
0x032FDF|$0C:$AFCF:A5 46    LDA $46
0x032FE1|$0C:$AFD1:E9 14    SBC #$14     <<< -20 from # of hits counter... why?
0x032FE3|$0C:$AFD3:85 46    STA $46
0x032FE5|$0C:$AFD5:A5 47    LDA $47
0x032FE7|$0C:$AFD7:E9 00    SBC #$00
0x032FE9|$0C:$AFD9:85 47    STA $47
0x032FEB|$0C:$AFDB:B0 07    BCS $AFE4
0x032FED|$0C:$AFDD:A2 01    LDX #$01
0x032FEF|$0C:$AFDF:86 46    STX $46
0x032FF1|$0C:$AFE1:CA      DEX
0x032FF2|$0C:$AFE2:86 47    STX $47


While poking around I did find that setting that $14 to 0 made characters hit 36 times instead of 16. No idea what math is going on there that such a specific subtraction is necessary, but this routine clearly has something to do with number of hits.

EDIT: I think I'm on the right track. Reloading the same state over and over where damage is already determined, and tracking down the hex values for the two damage bytes. I have found where there is an addition of Ripper's damage being added, and my theory is that it's using two different values for actual damage calculations and display damage.


; control flow target (from $B177, $B227)
0x033341|$0C:$B331:18      CLC
0x033342|$0C:$B332:A5 9A    LDA $9A
0x033344|$0C:$B334:65 04    ADC $04
0x033346|$0C:$B336:85 9A    STA $9A
0x033348|$0C:$B338:A5 9B    LDA $9B
0x03334A|$0C:$B33A:65 05    ADC $05
0x03334C|$0C:$B33C:85 9B    STA $9B
0x03334E|$0C:$B33E:60      RTS


Right here is where the adjustment is made. Firion hits 15x for 2381 (but it's actually 2081, 300 / 15 = 20 per hit of Ripper) which is $4D $09 as opposed to $21 $08. 300 is $2C $01.


033342:A5 9A     LDA $009A = #$21
033344:65 04     ADC $0004 = #$2C
033346:85 9A     STA $009A = #$4D
033348:A5 9B     LDA $009B = #$08
03334A:65 05     ADC $0005 = #$01
03334C:85 9B     STA $009B = #$09


As you can see, the discrepancy happens here. It may be that by the time this is stored, the game has already calculated the damage to deal, while this number is now only being used for display. $04 and $05 are used for a lot of ROR through the RNG routine, so I couldn't very well step through until I found when Ripper was using these values, but the issue appears to be that Ripper's damage is calculated too late to be used for actual damage. The first time $9A and $9B, our damage numbers, are read or written to is likely when the actual damage calculation is done.


; control flow target (from $B0A0)
0x0330BF|$0C:$B0AF:A0 02    LDY #$02
0x0330C1|$0C:$B0B1:B1 A1    LDA ($A1),Y
0x0330C3|$0C:$B0B3:85 46    STA $46
0x0330C5|$0C:$B0B5:A9 00    LDA #$00
0x0330C7|$0C:$B0B7:85 47    STA $47
0x0330C9|$0C:$B0B9:A5 9C    LDA $9C
0x0330CB|$0C:$B0BB:85 48    STA $48
0x0330CD|$0C:$B0BD:20 88 BC JSR $BC88
0x0330D0|$0C:$B0C0:A5 4A    LDA $4A
0x0330D2|$0C:$B0C2:85 9A    STA $9A
0x0330D4|$0C:$B0C4:A5 4B    LDA $4B
0x0330D6|$0C:$B0C6:85 9B    STA $9B
0x0330D8|$0C:$B0C8:A5 9B    LDA $9B
0x0330DA|$0C:$B0CA:29 80    AND #$80
0x0330DC|$0C:$B0CC:F0 06    BEQ $B0D4
0x0330DE|$0C:$B0CE:A9 00    LDA #$00
0x0330E0|$0C:$B0D0:85 9A    STA $9A
0x0330E2|$0C:$B0D2:85 9B    STA $9B


So Ripper's damage needs to be called upon before this final STA $9A and STA $9B to actually apply the damage. After chasing the control flow backwards from where Ripper damage IS added in, I found this little routine which I do believe is the Ripper routine.


; indirect control flow target (via $B129)
0x033224|$0C:$B214:A5 9C    LDA $9C
0x033226|$0C:$B216:85 00    STA $00
0x033228|$0C:$B218:A9 00    LDA #$00
0x03322A|$0C:$B21A:85 01    STA $01
0x03322C|$0C:$B21C:A9 14    LDA #$14
0x03322E|$0C:$B21E:85 02    STA $02
0x033230|$0C:$B220:A9 00    LDA #$00
0x033232|$0C:$B222:85 03    STA $03
; call to code in a different bank ($0F:$FC98)
0x033234|$0C:$B224:20 98 FC JSR $FC98  ; 16-bit multiplication (little endian): $00-$01 * $02-$03, product stored in $04-$07; leaves X at #$00, Y not changed
0x033237|$0C:$B227:4C 31 B3 JMP $B331


This flows directly into that final write into $9A and $9B, after which damage has already been locked in. So it's a matter of changing control flow somewhere, to have this routine called upon earlier, or perhaps have wherever damage is finalized called on later.

Cyneprepou4uk

QuoteI'd really rather not try to play through the game all the way up to that point again

Make a movie of your walkthrough in fceux, and also record it on video. Then you can check with that video and start playing the movie from necessary frame.

abw

Disassembly updated (re-assemblable version is currently dead until I get around to finding out what ca65 is complaining about) with more labels and comments, including finding the weapon/armor and music data and correcting some parts of the RAM map. There's an extra byte in the weapon/armor data that somebody more familiar with game mechanics might recognize: the 3rd byte of all your armor data and the 5th byte of all your weapon data get summed and capped at #$FF, and this value gets copied to both in-battle (offset #$24) and out-of-battle (offset #$2F) stats but isn't displayed anywhere. I see it gets subtracted from your Intellect/Spirit spell stat when casting in battle, but haven't traced it any further than that.

Quote from: redmagejoe on January 26, 2020, 09:56:47 PM
The return of... the Evasion/Magic Defense Level Up Delay! ::)
($7E),Y refers to the character's Evasion/Magic Resist SKILL level/experience, which is different from the character's Evasion/Magic Resist attempts/success % STAT in ($7A). So it looks like the skill is levelling correctly, but then the skill increase doesn't get applied to the stat until the code you found earlier at $00:$9A7B runs and sets the attempts stat to the skill level +1.

Looking more closely at the Evasion/Magic Resist level up routine, however, it appears to share the same underflow bug that affects levelling up weapon skills; I haven't tested it, but it looks like if your Evasion/Magic Resist is level 10+, being attacked once in a rank 1 battle ought to cause the SBC ($7E),Y to underflow, resulting in SBC #$0A not clearing C and you gaining enough experience to increase your level.

Quote from: Leviathan Mist on February 01, 2020, 09:32:24 AM
I just took a quick look at the FF2 NSF file. Looks like a completely different system. Which means it would take some time to decode everything. I wouldn't hold my breath on a timely release of any ported songs.
It looks like BGM stuff starts around $0D:$9800, with the pointers to music data starting at $0D:$9E0D. Battle SFX stuff appears to start at $05:$BA00.

BlazeHeatnix

Quote from: Bregalad on February 02, 2020, 04:13:11 PM
I'm surprised you're surprised of this. You can hear it right away. FF1's sound engine is very limited, even compared to other 1987 NES games, while FF2 is much more featured. However FF3 sound engine sounds like an upgrade of FF2's. And other games such as Minna no Taabou no Nakayoshi Dai Sakusen, sounds the same as FF2 or FF3. I didn't look at any line of code to assert such a thing, though.

For the music my opinion is to not touch it, unless it is a bugfix. The remixes used in Danws of Souls are not by Uematsu. But also, it's part of history of the series that the Prelude and Chocobo theme were originally composed simpler as their later versions, and were expanded in FF4 and FF3 respectively. FF1 and FF2 not having boss themes (except for some bosses in FF2) is also part of the series.

It'd be an optional patch anyway. It's not like you have to use it and the bugfixes at the same time.

redmagejoe

#197
Quote from: abw on February 02, 2020, 11:42:10 PM
Disassembly updated (re-assemblable version is currently dead until I get around to finding out what ca65 is complaining about) with more labels and comments, including finding the weapon/armor and music data and correcting some parts of the RAM map. There's an extra byte in the weapon/armor data that somebody more familiar with game mechanics might recognize: the 3rd byte of all your armor data and the 5th byte of all your weapon data get summed and capped at #$FF, and this value gets copied to both in-battle (offset #$24) and out-of-battle (offset #$2F) stats but isn't displayed anywhere. I see it gets subtracted from your Intellect/Spirit spell stat when casting in battle, but haven't traced it any further than that.

I guess this is the total malus value from heavy armors against your spell's power. Certain weapons and heavy armors make you less effective as a caster, encouraging magic main characters to be almost naked or wear light armor and sit in the back row.

Quote from: abw on February 02, 2020, 11:42:10 PM
($7E),Y refers to the character's Evasion/Magic Resist SKILL level/experience, which is different from the character's Evasion/Magic Resist attempts/success % STAT in ($7A). So it looks like the skill is levelling correctly, but then the skill increase doesn't get applied to the stat until the code you found earlier at $00:$9A7B runs and sets the attempts stat to the skill level +1.

Watching RAM at the time it runs the STA ($7E),Y in the state where Firion is about to finish a battle where he gains a MDef level, I see that it's actually setting Firion's $6232 (rather than $612C, wtf?) from 06 to 07. So it's actually pushing $6232 + 1 into $621C later? I feel like this could still be resolved by finding a way to force a total stat refresh at the end of a battle or when going to the pause menu or something.

Quote from: abw on February 02, 2020, 11:42:10 PM
Looking more closely at the Evasion/Magic Resist level up routine, however, it appears to share the same underflow bug that affects levelling up weapon skills; I haven't tested it, but it looks like if your Evasion/Magic Resist is level 10+, being attacked once in a rank 1 battle ought to cause the SBC ($7E),Y to underflow, resulting in SBC #$0A not clearing C and you gaining enough experience to increase your level.

I will have to think about how to address this, then. Also abw, I'm hoping you could be a second set of eyes to see if my orbs change is airtight. And chasing around the Ripper control flow gave me a headache, as I can't actually figure out when its bonus damage is being loaded into $04 and $05, but it's clearly not early enough for the game to use it for real damage numbers rather than just display purposes. Sorry about the bad info on that ADC #$14, I was grasping at straws.


0x01685F|$05:$A84F:F1 7E    SBC ($7E),Y ; Evasion/Magic Resist skill level
0x016861|$05:$A851:E9 0A    SBC #$0A    ; your first 10 points don't count for anything
0x016863|$05:$A853:90 17    BCC $A86C  ; not enough pain => no gain


Could I simply use a solution similar to what we used for weapon levels and spell levels? Put a BCC under the first SBC, and then set the 2nd SBC up 1 (#$0B) to act as a CLC into SBC #$0A? Of course would have to make 2 bytes of room for the new BCC but, would that work? I really should try to find a way to stick TAX and INX into the $A86D subroutine, since all 3 calls to it in the entire code go into the JSR with TAX and INX. I could free up 2 bytes in 3 places, but here at least, I'd need those 2 bytes for the TAX and INX in the subroutine for my BCC (the cap at 15 sub is right below the evasion code).


0x0165DB|$05:$A5CB:88      DEY        ; offset for spell level
0x0165DC|$05:$A5CC:B1 7E    LDA ($7E),Y ; spell level
0x0165DE|$05:$A5CE:AA      TAX       
0x0165DF|$05:$A5CF:E8      INX        ; increase spell level
0x0165E0|$05:$A5D0:20 6D A8 JSR $A86D  ; cap X at 15
0x0165E3|$05:$A5D3:8A      TXA       
0x0165E4|$05:$A5D4:91 7E    STA ($7E),Y ; write the new spell level
0x0165E6|$05:$A5D6:C8      INY        ; offset for spell experience


Actually, in all 3 calls to $A86D it has these exact same instructions. I think I may rewrite that subroutine and open up / shift a lot of space in those 3 routines and push it into a separate IPS or combine it with the Weapon and Spell fixes because of its dependency. I'll play around with it. That would free up 9 bytes per routine that calls to $A86D for a net gain of 18 bytes.

EDIT: This will likely free up more than 18 bytes, and would also essentially merge the Weapon Max Level fix, Spell Max Level fix, and Max Stat Increase fix as they're in the same addresses. Assuming I fix all branches and account for all pointers, however, this will free up a good chunk of space to be used for other subroutines we may need, especially since there's a number of rogue NOPs from my early fixes where I was trying to avoid moving things around. I feel confident enough to consolidate now, but I'm going to be working on it for a bit and will post it for review. At some point it may benefit abw if I were to provide him with my full stable IPS for comparison to his current disassembly so we're operating with the same addresses and open space.

abw

Quote from: redmagejoe on February 03, 2020, 04:09:59 AM
I guess this is the total malus value from heavy armors against your spell's power. Certain weapons and heavy armors make you less effective as a caster, encouraging magic main characters to be almost naked or wear light armor and sit in the back row.
Yeah, I figured it was probably something like that, but I didn't feel like tracking it down myself :P.

Quote from: redmagejoe on February 03, 2020, 04:09:59 AM
Watching RAM at the time it runs the STA ($7E),Y in the state where Firion is about to finish a battle where he gains a MDef level, I see that it's actually setting Firion's $6232 (rather than $612C, wtf?) from 06 to 07. So it's actually pushing $6232 + 1 into $621C later? I feel like this could still be resolved by finding a way to force a total stat refresh at the end of a battle or when going to the pause menu or something.
I gave this one a quick test and confirmed that Evasion does underflow and cause you to gain a level. Given the lack of post-battle message and the delay in your stat being updated from the skill increase, it would have been much harder to notice this bug than the weapon underflow bug. For the fix, I'd probably adjust the value of Y to match the stat offset and then INC ($7A),Y when the skill level increases.

Quote from: redmagejoe on February 03, 2020, 04:09:59 AM
Also abw, I'm hoping you could be a second set of eyes to see if my orbs change is airtight.
The Orb fix looks fine to me. If you really wanted to, you could extract

CLC
ADC #$0A    ; adds 10 to the appropriate stat
CMP #$64    ; prevent stat from going above 99, compare to 100
BCC $A1CA  ; does not exceed cap, proceed to store new stat value
LDA #$63    ; set stat to 99 if >99

into a separate function and JSR to it, which would free up another 2 bytes.

Quote from: redmagejoe on February 03, 2020, 04:09:59 AM
And chasing around the Ripper control flow gave me a headache, as I can't actually figure out when its bonus damage is being loaded into $04 and $05, but it's clearly not early enough for the game to use it for real damage numbers rather than just display purposes. Sorry about the bad info on that ADC #$14, I was grasping at straws.
For the Ripper bug, here's a longer straw: the 8th byte of weapon data looks kind of like a bit field, the Ripper is the only weapon that sets bit 4, and if I set bit 4 on Maria's starting bow, the game says she does 20+ damage against creatures with < 10 HP, but they don't die. Try changing $0C:$8184 from 10 to 00 and see what the Ripper does. That ought to make the displayed value match the actual damage, but in this case probably the right fix is to make the damage match the displayed value.

As another point of interest, assuming that 8th byte is some kind of racial/elemental/status/etc. attack modifier, I notice the Blood Sword sets bit 2, which might be what causes the extra damage against the Emperor, and that the Poison Axe is the only other weapon that also sets bit 2; if you have a save handy, want to try attacking the Emperor with a Poison Axe and see if you get any bonus damage?

Quote from: redmagejoe on February 03, 2020, 04:09:59 AM
Actually, in all 3 calls to $A86D it has these exact same instructions. I think I may rewrite that subroutine and open up / shift a lot of space in those 3 routines
Given the volume of fixes we're making to the level up routines, I'm also thinking it's becoming worthwhile to just take the entire section from $05:$A47C to $05:$A991 and optimize it to free up space for bugfixes.

redmagejoe

#199
Yep, I'm in the painful process of doing that as we speak. I'll be rolling our 3 aforementioned fixes into a single patch, as well as any change to the evasion/MDef underflow.  and I'm also seeing better ways to approach some of our fixes now that I have a better understanding of what the instructions are doing. I'm looking at a net gain of possibly ~30 bytes of space we can use for new subroutines if needed. It will be much cleaner overall.

Also would the underflow fix as I suggested work, using the same sort of fix you used to avoid underflow on weapons, which I also applied to spell levels? Having an extra branch after the first SBC?

Once I finish this time-consuming code-shifting/pointer-adjusting/optimizing/consolidating project, I'll take a look at the other suggestions. I didn't realize Blood Sword did extra damage to the Emperor, I was only aware that it did # of hits x 1/16 of target's Max HP, ensuring that 16 hits 1-shots anything. I'll look into all that later. I'd like to send you my stable version IPS soon so we're working on the same base, since these independent IPS files won't be isolated in the final product. I've only got them that way for the purposes of recovering if I break something and forget how to undo it.

@abw: Did you change this following chunk for either your HP/MP cap fix or the weapon level up fix? I have a ROM with only the HP/MP, weapon levels, spell levels, and max stat increase fixes applied, but I don't recall touching this section, and I don't even know what it does. It's outside the range I'm shifting up though, so I'm not that concerned, but I want to make sure I know which patch it came from when I bundle them together.

Original

; set or clear C based on 16-bit little endian subtraction: $00-$01 - $02-$03
; control flow target (from $A814)
0x0169C6|$05:$A9B6:38      SEC       
0x0169C7|$05:$A9B7:A5 00    LDA $00   
0x0169C9|$05:$A9B9:E5 02    SBC $02   
0x0169CB|$05:$A9BB:85 04    STA $04    ; completely pointless op, unnecessary and calling code doesn't care about this
0x0169CD|$05:$A9BD:A5 01    LDA $01   
0x0169CF|$05:$A9BF:E5 03    SBC $03   
0x0169D1|$05:$A9C1:05 04    ORA $04    ; completely pointless op, unnecessary and calling code doesn't care about this
0x0169D3|$05:$A9C3:60      RTS


Changed version in HEX
DD 39 A8 08 88 B1 7A 28 D0 03 DD 38 A8




Finally finished... I did it the way hard way, but I double-checked every pointer, every branch, adjusted as necessary, and even had to take account for pointers from outside the scope of what was changing. But managed to free up a chunk of 18 bytes in the middle of all our level up routines. I want to utilize some of it for the Evasion/MDef underflow fix before I post it up.