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

Poll

Restored: ROM space allowing, should attacks be tallied for each weapon type used in combat? (support multiple weapon EXP for weapon swapping)

No. Restored already has passive growth, only end-of-combat weapon should receive bonus.
Yes. All weapons used in combat should receive this bonus credit.

Author Topic: Final Fantasy II Restored  (Read 124916 times)

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #380 on: May 28, 2020, 07:49:25 pm »
I haven't encountered an Iron Giant yet, but I do feel that monsters flee too much in general. Dividing the HP difference by 64 (minimum 14444 party HP required for a 1% chance for a lone Iron Giant to run) or even 128 (25388 HP) instead of 32 (8972 HP) would be an easy change to make. That said, I've had an average over my recent playthroughs of about 7000 HP when reaching the final boss and haven't had any serious difficulties, so 12000 HP seems like a lot... maybe I've been abusing save states too much?

I've done a bit of farming for rare items early on, and I've avoided save stating at all except when I need to walk away for long periods of time, but I've more or less played the game as an end user in my testing. My HP might be a bit higher, but not by too much. Enemies fleeing right now feels fine given my HP, I just think we should set Iron Giant's formation flag as inescapable, honestly, tempting to set it on both. It doesn't seem like something that should run away, it has stats and even a Fear Score comparable to bosses, but the bosses won't run because they have the flag. As far as I can tell, he's meant to be a rare boss.

Based on your explanation of the math being done for fear in the original, it sounds like current behavior is pretty close to what the devs intended, and I think that's alright. The issue is almost entirely with the Iron Giant. After all, there's a lot of enemy formations that you just can't run away from and most of the enemies that would give you trouble regardless your HP, if you're not full-on munchkin twinked out, don't seem to run if only because you can't run either. Death Riders, Thunder Gigas, King Behemoth, the Dragons.
« Last Edit: May 30, 2020, 07:42:12 am by redmagejoe »

nosynose

  • Jr. Member
  • **
  • Posts: 39
    • View Profile
Re: Final Fantasy II Restored
« Reply #381 on: May 28, 2020, 11:10:56 pm »
I will upload the patch to my drive and link it here, while also updating the submission. Sorry about the inconvenience. https://tinyurl.com/ybk7sz2a
Yes, v2.2a Rev1 now runs okay with its B-Button-Dash applied!
Don't mind it :) Appreciate the quick fix and all your hard work here :thumbsup:

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #382 on: June 02, 2020, 09:40:21 pm »
Okay, time for some more updates:
  • FIXED ENOUGH: A weapon's family or element bonus can push its base damage over 1 byte, but the part of the damage algorithm that calculates a random number between 0 and base damage only uses the low byte of base damage, resulting in significantly reduced damage output. The random number is now calculated as a percentage (or whatever the right word for per-256-age is) of both bytes, but since the RNG only has 256 possible outputs, not every value will actually be obtainable; with at most 20/276 values being lost, the difference from a full 16-bit RNG should be nearly undetectable, however.
  • BUG FIX FIXED: When an enemy targets all characters with a spell, we were looping through all 4 character slots and incrementing each of their magic defense counters regardless of whether the character was actually targetted by the spell. Now each character's counter is incremented as the spell targets them, so characters that are skipped (due to being KO/Stone/not in the party) do not receive credit for attacks they did not receive.
  • FIXED: Monsters selecting spells to cast that they don't have enough MP for. Spells with costs higher then the monster's current MP at command selection time are now replaced by Attack.
  • FIXED: Magic not checking for Amnesia/Mute/Toad status at time of casting. Spells are now stopped at time of casting with the "Nothing happened." message if the caster has an ailment that prevents casting spells.
  • FIXED: Magic not checking for the caster having sufficient MP at the time of casting. Spells are now stopped at time of casting with the "Nothing happened." message if the caster lacks sufficient MP.
  • FIXED: Deduct MP cost of spells before completing their effects so that Osmose/Swap can completely restore MP.
  • NEW + FIXED: If character number X uses an item and monster number X uses a spell, monster number X did not have their spell's cost deducted from their current MP.
  • NEW + FIXED: If character number X uses an item that breaks and monster number X uses a spell, the last character to act before monster number X would lose the item in the same slot as character number X's broken item; probably this avoids a large number of other errors due to the removed item still affecting character stats.
Bug Fix and Restored patches, ASM, and readme updated. By my count we have now fixed over 60 of this game's bugs! :woot!:

On a slightly different topic, what do you think about making confuse take effect immediately? How about making confuse choose a command at random instead of always being a physical attack?

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #383 on: June 02, 2020, 09:45:20 pm »
Awesome work as always, abw! And that's a LOT of bugs fixed, indeed. Which of course means that's a lot of bugs in this game, hoo boy...

I think Confuse taking effect immediately qualifies in Bug Fix using the same concept of other statuses, lack of MP, etc, not being checked in the same turn. Confuse should definitely immediately result in the next attack being affected. As for doing a random command, I don't think that's necessary. Series convention has always been physical attacks, and in most cases where even a little bit of training took place, any character attacking your party physically can be pretty devastating. I think it's good for it to be the hindrance it is.

I'll update the first post.
« Last Edit: June 03, 2020, 03:32:45 pm by redmagejoe »

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #384 on: June 02, 2020, 09:53:00 pm »
Awesome work as always, abw! And that's a LOT of bugs fixed, indeed. Which of course means that's a lot of bugs in this game, hoo boy...
Still plenty more to go, though - I see at least 20 things on the Bug Fix to-do list!

I think Confuse taking effect immediately qualifies in Bug Fix using the same concept of other statuses, lack of MP, etc, not being checked in the same turn. Confuse should definitely immediately result in the next attack being affected.
Okay, that should be easy to add.

As for doing a random command, I don't think that's necessary. Series convention has always been physical attacks
I'm pretty sure 4/5/6 at least would randomly select spells too; I always hated it when Rosa started to burn through her precious MP after getting confused :(.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #385 on: June 02, 2020, 10:00:17 pm »
You're right, I see that it was handled differently depending on the installment. I think it would be best not to depart too much from source material, design-wise, for Restored though. I think we can leave it as it is. I also opted to remove the INT/SPR penalty removal from the Restored list, because after playing with it, I realize it's actually not too hard to have a good "mage" equipment setup where you only lose 0-20% of your bonus depending on good equipment choices. I feel that remakes also took too far the desire to make the game more accessible, and I don't think the armor penalties were all that hard to work around.

If you see anything on my list I neglected to remove, please say so. I've been trying to organize the items near similar items compared to when I first made it, but it's possible I've still overlooked curating it.

Quote
  • Monsters that are killed by poison/venom have their current HP set to 0 and KO Ailment bit set, but are not actually removed from battle; they remain valid targets (you can even cast Life on them to bring them back!) and need to attacked again in order to remove them from battle.

Did this already get fixed? I feel like it already got fixed.

Also the changes to MP costs/requirements are nice, makes the game feel much more polished, having tested the new version.
« Last Edit: June 03, 2020, 03:38:04 pm by redmagejoe »

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #386 on: June 03, 2020, 06:40:10 pm »
You're right, I see that it was handled differently depending on the installment. I think it would be best not to depart too much from source material, design-wise, for Restored though. I think we can leave it as it is.
It's also a lot easier. Adding new logic to randomly choose between Attack, Magic, and Item and then randomly choosing a spell/item and then deciding whether to target characters or monsters (and partially inverting item targetting) would take up a lot of space.

I also opted to remove the INT/SPR penalty removal from the Restored list, because after playing with it, I realize it's actually not too hard to have a good "mage" equipment setup where you only lose 0-20% of your bonus depending on good equipment choices. I feel that remakes also took too far the desire to make the game more accessible, and I don't think the armor penalties were all that hard to work around.
Agreed, as long as you know that there is a penalty system at all and what penalty each piece of equipment imposes.

If you see anything on my list I neglected to remove, please say so. I've been trying to organize the items near similar items compared to when I first made it, but it's possible I've still overlooked curating it.
Aside from Ultima being more-or-less fixed, everything else on that list is currently outstanding.

Quote
  • Monsters that are killed by poison/venom have their current HP set to 0 and KO Ailment bit set, but are not actually removed from battle; they remain valid targets (you can even cast Life on them to bring them back!) and need to attacked again in order to remove them from battle.
Did this already get fixed? I feel like it already got fixed.
Nope, that one is still on the to-do list; I probably won't get to documenting the end-of-round code until after the end-of-turn code, so it'll be a little while yet.


Good news: I freed up a decent amount of space (and saved many cycles) by converting calls to the 16-bit multiplication routine that were only using 8-bit values to use the 8-bit multiplication routine instead; the 8-bit routine only requires setting A and X (and usually A already held one of the required values) while the 16-bit routine requires setting all of $00, $01, $02, and $03, so that tended to save 10+ bytes of variable setup per call, leaving us with nearly 200 free bytes in bank C.

Bad news: I then promptly used half of that space for Confuse fixes :P.
  • FIXED: Make confusion take effect immediately.
  • NEW + FIXED: Confused characters do not check whether their random target is valid.
At command selection time, confused monsters would only select a valid monster target, but confused characters would select a character target indiscriminately, leading to much flogging of corpses, chipping of statuary, and if you lacked a 4th party member, ominous attacking of empty air that goes by the name of your most recent 4th party member. I've fixed that so that characters now select a valid character target at command selection time.

At command execution time, there was no check for confusion, so I added one. It gets a little tricky since there's currently no way to tell if the actor was confused at command selection time or not (we can re-examine this later if we find some free RAM), and if they were, I want to avoid automatic retargetting since the rest of the game doesn't do that. So, if the actor is confused, their command gets set to Attack, and then we check their previously selected target. If it's of the right type for a confused attack (i.e. targetting a single member of the actor's own party), then they keep that target (ineffective or not), otherwise we know they got confused during the current round, so they choose a new valid target.

So, Confuse is now even more dangerous than before!

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #387 on: June 04, 2020, 01:58:04 pm »
Are any of these calls in the battle routines? I can imagine a noticeable impact with the smaller overhead if so, like the very long pause between the last action of a round before Firion steps forward and the player can issue commands again. Something like 2-3 whole seconds of waiting.

As always abw, you are awesome. :)



I may be doing the math wrong, but I feel like maybe the passive skill growth is handling the formula weird? I'm assuming all that's happening with it is that it's adding 1 attack/cast to the counter for each weapon/spell, so by my understanding, Battle Rank 7 fights (the highest rank in the game) should allow a player to gain passive growth up to weapon levels 9 and spell levels 11.

Quote
Weapons and Shields: At the end of combat, you gain skill independently for the items in each hand, based on the number of attacks you made during the fight. Note that the game doesn't check what you were using when you made the attack, but rather assigns the skill advancement to whatever you were holding at the end of combat. If you're holding two of the same type of weapon, both will add progress points, effectively doubling your rate of progress. The modifier for weapon advancement is +1, so the formula is Rank + Attacks %u2212 Level + 1. Attacking a rank 1 monster with a level 1 weapon will thus result in 2 points of progress for the first attack, and 1 additional point for each subsequent attack during the same combat. Note that weapons are subject to the target-canceling exploit mentioned below.

Magic: Each of your known spells levels independently during combat, and you can progress in multiple spells during the same fight. The modifier for spells is +3, making the formula Rank + Times Cast %u2212 Level + 3. Casting a level 1 spell during a rank 1 fight will earn you 4 progress points for the first cast, and 1 point for each additional cast. It is thus prudent to mix up your spells during combat, since the first casting of each spell is generally worth the most progress. Magic is also subject to the target-canceling exploit described below. Note that magic spells cast outside of combat always gain 2 progress points per casting, regardless of level. You cannot cast a spell outside of combat unless it would have some effect.

Taking these formulas, again, assuming that 1 use is simply being added to the counter, Rank (7) + Attacks (1) - Level (8) + 1 = 1. Thus Weapons at Level 8 should gain 1 experience per battle. Same for spells being Rank (7) + Casts (1) - Level (10) + 3 = 1. Spells at Level 10 should gain 1 experience per battle. Currently though, it seems that my Level 10 spells and Level 8 weapons are not growing on battle comprised entirely of Rank 7 enemies, such as 3-4 Devil Wolves, or 2 Mythril Golems, or the like. The math works in Bug Fix and, if you ignore the passive growth, Restored, but it's simply the passive growth bonus that has me perplexed.

Is my assumption about the behavior of the passive growth incorrect? Is it simply doing a different minor addition based on difference in rank?
« Last Edit: June 05, 2020, 03:26:47 pm by redmagejoe »

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #388 on: June 05, 2020, 11:16:35 pm »
Are any of these calls in the battle routines? I can imagine a noticeable impact with the smaller overhead if so, like the very long pause between the last action of a round before Firion steps forward and the player can issue commands again. Something like 2-3 whole seconds of waiting.
Pretty much all of them, actually. And on that note, I'm also going to tweak the battle RNG to handle the case where the range is [0..255] specially, which is the only time it actually uses 16-bit multiplication, so after that the rest of the battle RNG can be switched to 8-bit multiplication too, freeing up a few more bytes in the fixed bank and saving plenty of cycles during battle.

Is my assumption about the behavior of the passive growth incorrect? Is it simply doing a different minor addition based on difference in rank?
Yes - passive skill growth doesn't change your number of uses, it allows growth with 0 uses. That was the only functional change to spells, but the weapon code was converted to a loop over each type; when dual-wielding weapons of the same type, usage now stacks for all weapon types (including fists, which the original game only ran one growth calculation for) instead of the original behaviour of running the growth calculation twice, which has a few implications, including at least: the rank bonus is only applied once, the level penalty is only applied once, you can no longer gain 2 skill levels in one battle, and fists now grow just as quickly as other weapon types. Dual-wielding low skill weapons against higher-ranked foes generates less growth than before since you only get one free boost instead of two, but dual-wielding high skill weapons against lower-ranked foes generates more growth since you only have to overcome the growth barrier once, not twice.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #389 on: June 11, 2020, 04:32:48 pm »
Quote
  • Consider adding running gross of lost HP/MP rather than net for end-of-battle growth calculations.

I decided to remove this as a goal for Restored, as after extensive playtesting I found it to be a largely unnecessary idea. With 0 beating up of my own team and a minor amount of early farming, my current party's HP before the final boss is 3726, 4629, 3837, and 4254. More than enough with endgame stats and gear to survive most onslaughts, and have all enemies in the game capable of running away from your party run away at their cap of 85% likelihood. Making HP easier to get would be redundant, I think. Same goes for MP, with my characters pre-grinding having totals between 360 and 590. It simply feels like ROM space we don't need to take up.



I wish I could make any sense at all of the map data, so I could at least contribute to some of the map-related fixes since you've been so diligently poring over the combat engine. Any advice on methods I might employ to try to decipher the map data table in an efficient manner, rather than just changing bytes and using process of elimination?

I see the map data appears to start at $01:$8200 and goes through $01:$BC3D, I just don't even know where to begin knowing what each byte translates to, let alone which "field" applies to which map, to begin manipulating bytes for deciphering this.



So something has gone decisively wrong in my Restored playtesting, and I'm not quite sure how to reproduce it. At some point, Maria's current MP was somewhere around 950, and I noticed towards the end of the battle it was suddenly ~400. Nothing Swapped her, Osmosed her, and I didn't burn a lot of MP on spells either. When I finally noticed this, I checked her MP outside of battle, and it was 902/999... Strange. Going back into battle, it was at 398, behaving as though I suddenly had two copies of her MP data. Very bizarre. I save stated and began testing just now, and after casting Fire 10 to put her down to 388 in battle, to see if it would carry over out of battle, I checked the menu, and she now has 9N2/999 MP... What exactly is happening here? After hours upon hours of stat training and battles, this is the first peculiarity I noticed with stats.

Upon further testing, namely using Osmose with Firion on her, she went from "377" down to 636, which displayed properly outside of battle. So just like when MP was uncapped, it was actually representing numbers HIGHER than 999 with letters. I have no idea how her current MP was able to flow outside of bounds above 999, especially given in the battle where it happened, no MP-adjusting spells were being used. I was fighting 3 Roundworms, who have no MP or spells, and the only spells I recall using on Maria were Curse (a number of times) and Blind. I will say that in this one battle, I Confused the Roundworms after multiple failures to succeed with Curse, as I just wanted them to be doing anything other than hitting my low HP Leon. I'm not sure if there's a correlation there, but it is the only time this has happened and also the only time I used Confuse recently.

Firion is the one who used Confuse, however, so I don't believe it's an MP cost issue. Some sort of branch error or the like with Confuse code? Uh oh... I think I might see the issue. When the Confused Roundworm attacked itself or its ally (new battle, decided to investigate), Maria's MAX HP went up by 1 twice. What data is being written to when Confused enemies attack each other?
« Last Edit: June 12, 2020, 01:14:16 am by redmagejoe »

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: Final Fantasy II Restored
« Reply #390 on: June 12, 2020, 03:21:10 pm »
Trying to figure out FF2's dungeon/town map data. My notes so far:

Map size: 32x32 tiles
RAM:
7000 - 73FF : decompressed map
7400 - 74FF : some kind of list - compressed map?
7500 - 70BF : at a glance, NPC coordinates and movement data?
7800 - 78FF : map tile info for row 1
7900 - 79FF : map tile info for row 2

This code decompresses the map two rows at a time.

Code: [Select]
L1D97:                   
 9D97  LDY $88       ; put tile counter ? in Y           
 9D99  LDX $7400,Y   ; get ??? in X           
 9D9C  LDY #$00                 
 9D9E  LDA $7800,X   ; get tile ID           
 9DA1  STA ($80),Y   ; save as map tile           
 9DA3  INY                     
 9DA4  LDA $7880,X   ; get tile ID +$80         
 9DA7  STA ($80),Y   ; save as map tile +1
 9DA9  LDY #$20      ; move up $20           
 9DAB  LDA $7900,X   ; get tile ID +$100           
 9DAE  STA ($80),Y   ; save as map tile +$20           
 9DB0  INY                     
 9DB1  LDA $7980,X   ; get tile ID +$180           
 9DB4  STA ($80),Y   ; save as map tile +$21           
 9DB6  LDA $80       ; load low byte of map tile pointer           
 9DB8  CLC                     
 9DB9  ADC #$02      ; add 2           
 9DBB  STA $80       ; save low byte of map tile pointer           
 9DBD  AND #$1F      ; keep it under 32 tiles
 9DBF  BNE L1DCC     ; if map tile = #$20 then jump ahead       
 9DC1  LDA $80       ; load low byte of map tile pointer           
 9DC3  CLC                     
 9DC4  ADC #$20      ; add $20 (next row)           
 9DC6  STA $80                 
 9DC8  BCC L1DCC     ; if it wrapped, jump ahead           
 9DCA  INC $81       ; else, increase the high byte of map tile pointer           
L1DCC:   
 9DCC  INC $88       ; increase the tile counter ?           
 9DCE  BNE L1D97     ; and jump back to loading the map until it wraps   
             

This is really confusing, I don't get how this is better than FF1's compression. It seems like there would be $300 bytes of data for each map, which is decompressed into $400 bytes. 768 bytes each. The largest map in FF1 is the second floor of the Mirage Tower, which is 1,632 bytes... but the average is about 700-800, which is again, 64x64 tiles... four times larger than FF2's maps.

UNLESS... 7400 is the decompressed map, and 7800 and 7900 are something else, possibly shared information for multiple maps?

I need to find where the data to 7800 and 7900 gets written into RAM next, maybe that will clear something up.



Bank 4 starts with #96 pointers (96 maps!) to compressed $7400 map data. This part is as expected. The data is compressed in the same format as FF1's maps.

Code: [Select]
L3D39F:                 
  D39F  LDY #$00                 
  D3A1  LDA ($80),Y   ; load compressed map byte           
  D3A3  BPL L3D3D0    ; if below $80, branch to single-tile writing
  D3A5  CMP #$FF      ; if = $FF, branch to RTS           
  D3A7  BEQ L3D3E1               
  D3A9  AND #$7F      ; remove high bit to get tile ID           
  D3AB  STA $84                 
  D3AD  INC $80       ; increment pointer           
  D3AF  BNE L3D3B3               
  D3B1  INC $81       ; increment high byte if pointer wrapped           
L3D3B3:   
  D3B3  LDA ($80),Y   ; get second byte (amount of tiles)           
  D3B5  TAX           ; put it in X           
  D3B6  LDA $84       ; then reload the tile ID           
L3D3B8:   
  D3B8  STA ($82),Y   ; save the tile to $7400           
  D3BA  INY           ; increment the destination           
  D3BB  BEQ L3D3C8    ; branch to increment the destination high byte if it wraps           
  D3BD  DEX           ; subtract the tile count by 1           
  D3BE  BNE L3D3B8    ; if X = 0, branch to increment pointer
  D3C0  TYA                     
  D3C1  CLC                     
  D3C2  ADC $82       ; $82 = total tiles written? ; add Y to total?
  D3C4  STA $82                 
  D3C6  BCC L3D3CA    ; if carry clear, branch ahead           
L3D3C8:   
  D3C8  INC $83       ; increment high byte of pointer destination           
L3D3CA:   
  D3CA  INC $80       ; increment source pointer           
  D3CC  BNE L3D39F    ; if it is NOT yet wrapped to 0, get next byte in compressed map data
  D3CE  BEQ L3D3DC    ; else, branch ahead           
L3D3D0:   
  D3D0  STA ($82),Y   ; for single tiles, just prints the tile to the destination           
  D3D2  INC $82       ; increment the destination           
  D3D4  BNE L3D3D8               
  D3D6  INC $83       ; increment the high byte if low byte wrapped           
L3D3D8:   
  D3D8  INC $80       ; increment the source pointer           
  D3DA  BNE L3D39F               
L3D3DC:   
  D3DC  INC $81       ; increment the high byte if the low byte wrapped           
  D3DE  JMP L3D39F    ; and jump to resume loop           
L3D3E1:   
  D3E1  RTS                     

Now the mystery of 7800 and 7900 to come.



A correction for the disassembly:

ZP RAM $48 = current map (map ID)
ZP RAM $2D = mapflags (not Map ID)

Aha, I think I get it now. I'm not sure what the term for it is... blocks, metatiles? So, yeah:

7800 is the upper 2 tiles, 7900 is the lower 2 tiles. These are basically giant tilemaps and I'm willing to bet they ARE re-used for multiple maps. Each byte of 7400 represents a 2x2 block. So an FF2 map editor would need to piece together these blocks. And the compressed map data can be super tiny as a result, but the maps themselves can't be THAT complicated, since there's only so many combinations of 4 blocks.

Neat!
« Last Edit: June 12, 2020, 04:52:04 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #391 on: June 12, 2020, 07:44:38 pm »
I decided to remove this as a goal for Restored, as after extensive playtesting I found it to be a largely unnecessary idea.
In the original game, I'm okay with HP growth, but MP growth is pretty annoying; once your max MP gets up to 50 or so, it's really hard to raise it when all you have are level 1-2 spells; Restored's passive skill growth fixes that problem at least. You can still run into shortages on characters who only cast out-of battle spells, though, since that MP expenditure has no chance to increase max MP.

So something has gone decisively wrong in my Restored playtesting
Ha, this was the physical equivalent of a bug I fixed earlier for magic - when a monster targets a monster, the high bit of the target byte is set, but I wasn't checking for that, so incrementing attack counters was operating on an address #$80 higher than it should have, which pushed it into battle stats.

Trying to figure out FF2's dungeon/town map data. My notes so far:
Nice - I've added your comments to the disassembly!

Time for some more updates. In addition to a couple of fixes, large sections of the battle setup code in bank B have now been documented, including an unexpected 6502 implementation of quicksort - with 5 stack bytes consumed for each level of recursion, it's a good thing the game never calls this routine with more than 12 items!

Bug Fix + Restored:
  • BUG FIX FIXED: Incrementing counters for physical attacks received from monsters didn't take monsters attacking themselves into account, resulting in other battle stats being erroneously affected.
  • FIXED: In enemy formations in Fynn Castle that contains both Dual Heads and Dual Deads, the pre-battle enemy name list always assumes that there are Stalagmites as well when there are none.
  • FIXED: Killer Fish use the wrong palette depending on their companions.
Restored:
  • FIXED: Make Iron Giant battles inescapable.
And here's a new bug for the list:
  • NEW: The code for printing "しょうひMP" (MP Cost) in the battle magic menu doesn't set the memory address used to hold the menu window width before adding the string to the CHR buffer, so the width uses the previous value of that address, which happens to be the tile ID for the ones digit of the character's maximum MP. This bug isn't triggered in the Japanese version since "しょうひMP" doesn't contain any diacritics and is unlikely to affect translations into scripts that only use 1 row for their characters.

I haven't checked, but the Stalagmite issue probably affected other battles as well. The cause of the problem was that the game might randomly generate more monsters for an encounter than fit on screen, but when an entire group didn't fit, the name of the omitted group was not removed from the list of monster groups to display.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: Final Fantasy II Restored
« Reply #392 on: June 12, 2020, 08:06:39 pm »
Nice - I've added your comments to the disassembly!

Cool! :D I did a little more digging, don't know exactly how right I am about it, but...

Code: [Select]
L1D52:                   
 9D52   LDA $48       ; get map ID           
 9D54   LSR A                   
 9D55   LSR A                   
 9D56   LSR A                   
 9D57   LSR A         ; left shift 4 times           
 9D58   ORA #$A0                 
 9D5A   STA $81       ; save as high byte of pointer           
 9D5C   LDA $48       ; get map ID           
 9D5E   ASL A                   
 9D5F   ASL A                   
 9D60   ASL A                   
 9D61   ASL A         ; right shift 4 times           
 9D62   STA $80       ; save as low byte of pointer           
 9D64   LDY #$0F      ; set following loop to 16           

;; Starting town's map ID is 5, resulting in a 16 bit pointer: $A050

L1D66:                   
 9D66   LDA ($80),Y   ; copy 16 bytes (some kind of info about the map?)
 9D68   STA $0780,Y             
 9D6B   DEY                     
 9D6C   BPL L1D66     ; when Y = $FF, stop[/td]

Code: [Select]
F1E3B:                   
 9E3B  LDA $0780         
 9E3E  AND #$80                 
 9E40  STA $49                 
 9E42  LDX #$00                 
L1E44:   
 9E44  LDA $8B00,X    ; copy $100 bytes to 0400 for something             
 9E47  STA $0400,X    ; most likely tile properties                         
 9E4A  INX           
 9E4B  BNE L1E44     
 9E4D  LDX $48        ; get current map ID in X
 9E4F  LDA $B300,X    ; get a byte from B300, I assume its a table         
 9E52  LSR A          ; left shift the byte, to set carry         
 9E53  LDX #$3F       ; amount of loops to do, really $40         
 9E55  BCS L1E92      ; if carry was set, load from +$100         
 
 ;; these values are guesses based on FF1's structure
 ;; the UL, UR, LL, LR tile graphics are 8x8 pixels
 ;; and combined into 1 16x16 pixel tile later
 
L1E57:   
 9E57  LDA $8400,X             
 9E5A  STA $0500,X    ; upper left tile graphic           
 9E5D  LDA $8440,X             
 9E60  STA $0580,X    ; upper right tile graphic         
 9E63  LDA $8480,X             
 9E66  STA $0600,X    ; lower left tile graphic
 9E69  LDA $84C0,X             
 9E6C  STA $0680,X    ; lower right tile graphic         
 9E6F  LDA $8700,X             
 9E72  STA $7800,X    ; upper left 2x2 metatile         
 9E75  LDA $8740,X             
 9E78  STA $7880,X    ; upper right 2x2 metatile         
 9E7B  LDA $8780,X             
 9E7E  STA $7900,X    ; lower left 2x2 metatile         
 9E81  LDA $87C0,X             
 9E84  STA $7980,X    ; lower right 2x2 metatile         
 9E87  LDA $8A00,X             
 9E8A  STA $0700,X    ; attribute ? for metatile ?         
 9E8D  DEX                     
 9E8E  BPL L1E57      ; loop until ...         
 9E90  BMI L1ECB      ; high bit set (X = $FF), then branch

L1E92:                ; same, but load from +$100
 9E92  LDA $8500,X             
 9E95  STA $0500,X    ; upper left tile graphic           
 9E98  LDA $8540,X                       
 9E9B  STA $0580,X    ; upper right tile graphic           
 9E9E  LDA $8580,X                       
 9EA1  STA $0600,X    ; lower left tile graphic         
 9EA4  LDA $85C0,X                       
 9EA7  STA $0680,X    ; lower right tile graphic           
 9EAA  LDA $8800,X                       
 9EAD  STA $7800,X    ; upper left 2x2 metatile           
 9EB0  LDA $8840,X                       
 9EB3  STA $7880,X    ; upper right 2x2 metatile           
 9EB6  LDA $8880,X                       
 9EB9  STA $7900,X    ; lower left 2x2 metatile           
 9EBC  LDA $88C0,X                       
 9EBF  STA $7980,X    ; lower right 2x2 metatile           
 9EC2  LDA $8A40,X                       
 9EC5  STA $0700,X    ; attribute ? for metatile ?           
 9EC8  DEX                     
 9EC9  BPL L1E92      ; loop until high bit set (X = $FF)
L1ECB:   
 9ECB  LDX #$3F       ; another $40 loops... same data no matter what the map ID is         
L1ECD:   
 9ECD  LDA $8600,X             
 9ED0  STA $0540,X    ; upper left tile graphic ?             
 9ED3  LDA $8640,X                       
 9ED6  STA $05C0,X    ; upper right tile graphic ?           
 9ED9  LDA $8680,X                       
 9EDC  STA $0640,X    ; lower left tile graphic ?         
 9EDF  LDA $86C0,X                       
 9EE2  STA $06C0,X    ; lower right tile graphic ?           
 9EE5  LDA $8900,X                       
 9EE8  STA $7840,X    ; upper left 2x2 metatile ?           
 9EEB  LDA $8940,X                       
 9EEE  STA $78C0,X    ; upper right 2x2 metatile ?           
 9EF1  LDA $8980,X                       
 9EF4  STA $7940,X    ; lower left 2x2 metatile ?           
 9EF7  LDA $89C0,X                       
 9EFA  STA $79C0,X    ; lower right 2x2 metatile ?           
 9EFD  LDA $8A80,X                       
 9F00  STA $0740,X    ; attribute ? for metatile ?           
 9F03  DEX                     
 9F04  BPL L1ECD      ; loop until high bit set (X = $FF)         
 9F06  LDA $0786               
 9F09  STA $044D               
 9F0C  STA $046F      ; these 2 are copies of the same byte for some reason         
 9F0F  LDX $48        ; get map ID in X         
 9F11  LDA $B000,X    ; use it to load a byte from another table?         
 9F14  LSR A                   
 9F15  LSR A                   
 9F16  LSR A                   
 9F17  LSR A                   
 9F18  LSR A          ; left shift it 5 times and put in X         
 9F19  TAX                     
 9F1A  LDA $83C2,X    ; which is used to read from ANOTHER table?           
 9F1D  STA $0738      ; then saved twice         
 9F20  STA $0716               
 9F23  RTS

I think this should account for all that "indirect data load target" stuff in Bank 0.
« Last Edit: June 12, 2020, 08:27:35 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #393 on: June 12, 2020, 08:11:32 pm »
I significantly updated the first post to clean things up and rearrange information based on importance. I particularly wanted to highlight the contributors of the project since this project is far beyond anything I think I could have ever undertaken on my own, and I want to be sure all you awesome people are given credit due.

:woot!:

Quote
The code for printing "%u3057%u3087%u3046%u3072%uFF2D%uFF30" (MP Cost) in the battle magic menu doesn't set the memory address used to hold the menu window width before adding the string to the CHR buffer, so the width uses the previous value of that address, which happens to be the tile ID for the ones digit of the character's maximum MP. This bug isn't triggered in the Japanese version since "%u3057%u3087%u3046%u3072%uFF2D%uFF30" doesn't contain any diacritics and is unlikely to affect translations into scripts that only use 1 row for their characters.

Based on how I'm reading this then, this is more or less a non-issue bug then, isn't it? I mean, not that we shouldn't consider fixing it at all, but it's pretty low priority, right?



Erm, it seems that something in the latest Restored (and Bug Fix too) update is not playing nicely with the Chaos Rush translation, causing a great deal of garbled text in combat messages. I do believe load order didn't matter prior to this version, and though it seems to look fine if I do the translation second... well we both know that simply means that something important is probably being excluded or overwritten.

I decided to test the old Demiforce version with the patches to see if this issue persisted there, and everything seems to work fine. I compared a Demiforce-only and ChaosRush-only ROM and it looks like there may be a few differences outside the script which may be an issue. I didn't think there were any code changes made by Chaos Rush, but without further investigation, I won't know precisely what the issue is. I've just used PatchChecker (determining that Demiforce and Restored are 100% compatible) to find that the new Restored (and probably Bug Fix) is 98.8% compatible with Chaos Rush. I'll have a look and see where the problem area is.

Code: [Select]
\FFII_ChaosRushENTranslation_v2.2a.ips
1. 03160C:
[1A] [C9] [6E] [B0] [10] [86] [DD] [AA] [BD] [DA] [EE] [48] [BD] [A7] [EE] [A6] [DD] [91] [6C] [C8] [68] [91] [6C] [E8] [C8] [D0] [E1] [60]

2. 031628: (irrelevant)
[FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF] [FF]

\restored.ips
1. 03160C:
[4E] [C9] [6E] [B0] [44] [C9] [64] [90] [17] [48] [A9] [C1] [85] [6A] [68] [20] [4E] [96] [C9] [69] [B0] [05] [18] [69] [3F] [D0] [2E] [18] [69] [7A] [D0] [29] [48] [A9] [C0] [85] [6A] [68] [20] [4E] [96] [C9] [5F] [90] [06] [18] [69] [84] [4C] [45] [96] [C9] [50] [90] [06] [18] [69] [7F] [4C] [45] [96] [C9] [4B] [90] [05] [18] [69] [58] [D0] [03] [18] [69] [53] [91] [6C] [E8] [C8] [D0] [AD] [60] [EA] [EA]

Huh, he actually did change some code. According to the disASM, that appears to be the code for writing to string buffer... Any ideas how I can make the Chaos Rush patch compatible with the new changes?
« Last Edit: June 13, 2020, 12:44:39 pm by redmagejoe »

abw

  • Hero Member
  • *****
  • Posts: 528
    • View Profile
Re: Final Fantasy II Restored
« Reply #394 on: June 13, 2020, 12:51:54 pm »
Cool! :D I did a little more digging, don't know exactly how right I am about it, but...
[...]
I think this should account for all that "indirect data load target" stuff in Bank 0.
Awesome, I'll add those notes to the disassembly too! One thing to note, though: you've got your shift directions backwards - it's Logical Shift RIGHT and Arithmetic Shift LEFT ;).

Based on how I'm reading this then, this is more or less a non-issue bug then, isn't it? I mean, not that we shouldn't consider fixing it at all, but it's pretty low priority, right?
Yeah, probably it would only affect Japanese text hacks. I think it was only a 2-byte fix, though, so I might toss it in anyway just for the sake of completeness.

Erm, it seems that something in the latest Restored (and Bug Fix too) update is not playing nicely with the Chaos Rush translation, causing a great deal of garbled text in combat messages. I do believe load order didn't matter prior to this version, and though it seems to look fine if I do the translation second... well we both know that simply means that something important is probably being excluded or overwritten.
That'll be the battle DTE code changes in the Chaos Rush patch. Applying our patch before the translation patch will be fine.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #395 on: June 13, 2020, 12:54:18 pm »
I'll have to make a note to mention that on the hack page, now that load order matters.
« Last Edit: June 13, 2020, 06:00:16 pm by redmagejoe »

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: Final Fantasy II Restored
« Reply #396 on: June 13, 2020, 05:42:02 pm »
Oopsie on the shifting... Thanks for catching it though.

I tracked down even more map loading code. I thought FF2 only had 96 maps, but it actually has 64 more pointers in Bank 05. (Only 54 actually used.)

Code: [Select]
F3D341:                 
  D341  LDA #$00                 
  D343  JSR F3FE03               
  D346  LDX $48       ; get map ID in X
  D348  LDA $B200,X   ; use to get from LUT
  D34B  PHA           ; push value
  D34C  ASL A         ; shift high bit into carry
  D34D  ROL A         ; then shift carry into lowest bit
  D34E  AND #$01      ; clear out every bit EXCEPT the lowest bit
  D350  ORA #$04      ; then ORA with the map bank ($04)
  D352  JSR F3FE03    ; and swap to that bank ($04 or $05) (Bank 04 has 96 maps, Bank 05 has 64)
  D355  PLA           ; pull the value from before
  D356  ASL A         ; double it, and put in X
  D357  TAX           
  D358  LDA $8000,X   ; Load the low byte of the compressed map data pointer and put in $80
  D35B  STA $80       
  D35D  LDA $8001,X   ; And do the same with the high byte
  D360  STA $81       
  D362  LDA #$00     
  D364  STA $82       
  D366  LDA #$74     
  D368  STA $83       
  D36A  JSR F3D39F   
  D36D  LDA #$00     
  D36F  JSR F3FE03   
  D372  JMP $9C00     

I think this means $48 is actually map INDEX and not ID? I get the two mixed up a lot.

Counted through the LUT at $B200 and came up with this graph:

Code: [Select]
------ Bank 04 -------;;-- Bank 05 --
00    ; 20 3   ; 40 2 ;; 80    ; A0     
01 2  ; 21 3   ; 41   ;; 81    ; A1     
02    ; 22 2   ; 42   ;; 82    ; A2 2   
03    ; 23 13  ; 43 4 ;; 83    ; A3 2   
04    ; 24 6   ; 44 4 ;; 84 2  ; A4 2   
05    ; 25 9   ; 45 3 ;; 85 2  ; A5     
06    ; 26     ; 46 3 ;; 86    ; A6     
07    ; 27     ; 47   ;; 87    ; A7     
08    ; 28     ; 48   ;; 88    ; A8     
09    ; 29     ; 49 2 ;; 89    ; A9     
0A    ; 2A     ; 4A   ;; 8A    ; AA     
0B    ; 2B 2   ; 4B 2 ;; 8B    ; AB     
0C    ; 2C     ; 4C   ;; 8C    ; AC     
0D    ; 2D     ; 4D   ;; 8D    ; AD     
0E 20 ; 2E     ; 4E   ;; 8E    ; AE     
0F    ; 2F - 0 ; 4F   ;; 8F 2  ; AF 2   
10    ; 30     ; 50   ;; 90    ; B0     
11    ; 31     ; 51   ;; 91    ; B1     
12    ; 32     ; 52   ;; 92    ; B2     
13    ; 33     ; 53 2 ;; 93    ; B3     
14 2  ; 34 2   ; 54 2 ;; 94    ; B4 2   
15    ; 35     ; 55 2 ;; 95    ; B5     
16 11 ; 36     ; 56 2 ;; 96    ;
17    ; 37 2   ; 57 2 ;; 97    ;
18    ; 38 2   ; 58   ;; 98    ;
19 4  ; 39 2   ; 59   ;; 99    ;
1A 3  ; 3A     ; 5A   ;; 9A    ;
1B 3  ; 3B     ; 5B   ;; 9B    ;
1C 2  ; 3C 2   ; 5C   ;; 9C    ;
1D 5  ; 3D     ; 5D   ;; 9D    ;
1E    ; 3E     ; 5E   ;; 9E    ;
1F 3  ; 3F     ; 5F   ;; 9F    ;

According to this, map $2F doesn't appear in the game? But the disassembly still has it as being loaded at some point. Map $0E wins the award for showing up #20 times in the LUT!



https://drive.google.com/file/d/1hTlvc8lg_qW4dYyFrLTAAJOdtAG5KLuj/view?usp=sharing

Disch made some python scripts for decompressing and re-compressing FF1's maps. I've edited one to work for FF2's maps. The re-compression will work for both games. I also made .exe files so no one has to download Python to use them, but they're 9 megabyte each, I don't really know how to turn a python script into an executable and have it small. *shrug*

For descompressing:
FF1's assumes the ROM is named ff.nes, and FF2's assumes it is named ff2.nes. Both can be run by double-clicking the .exe with the ROM in the same folder.

For the re-compressor:
Quote
Example usage:    python ffcompress.py maps\00.bin
The above will create the file 'maps\00.cmap' which will be the compressed map.
Additionally wildcard characters will work, so you can do this:    python ffcompress.py maps\*.bin
And it will compress ALL .bin files in that directory and create their respective .cmap file
Also, the compressor will examine 'last modified' timestamps and will only recompress maps if their cmap file is out of date.  So you can run this in a build step and it will mostly do nothing (and thus run very fast) unless you have recently modified a map.
However, this behavior can be ignored if you do:  python ffcompress.py yourfile.bin -f
The '-f' will force compression to happen even if the cmap file is up to date.
Last thing to note:
A compressed overworld map WILL contain a pointer table.  However compressed standard maps DO NOT.
I figure it'd make more sense for the standard maps to be individual files that can be incbin'd in the source, and you can probably use labels in ca65 to generate the pointer table.

There is a slight difference in re-compression, being that FF2 normally will use a run byte followed by a 2, for 2 tiles in a row, while this script will just put the base tile twice in a row... which is actually a tiny bit faster for the game's own decompression!

Original data: $87,$31,$80,$07,$01,$87,$08,$08,$22,$0A,$22,$0A,$22,$0A,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$0B,$94,$02,$40,$94,$03,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$13,$82,$02,$0F,$82,$03,$09,$87,$08,$8A,$03,$16,$08,$8A,$02,$11,$87,$0B,$0A,$11,$87,$4A,$FF
Recompressed data: $87,$31,$80,$07,$01,$87,$08,$08,$22,$0A,$22,$0A,$22,$0A,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$0B,$14,$14,$40,$94,$03,$09,$87,$08,$0B,$94,$06,$09,$87,$08,$13,$02,$02,$0F.$82,$03,$09,$87,$08,$8A,$03,$16,$08,$0A,$0A,$11,$87,$0B,$0A,$11.$87,$4A,$FF
« Last Edit: June 14, 2020, 05:29:42 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #397 on: June 15, 2020, 12:35:57 pm »
This looks pretty elaborate. I'm assuming at current, progress in decompressing is leading us towards deciphering what needs to be changed to affect what in each map, but since it is compressed, changing the actual bytes as they are won't actually have the desired effect, right? We'd need to make the changes to the decompressed map and the final bytes changed would be a reflection of the compressed data. I'd like to get back to making contributions, so ultimately my goal is to be able to fix the inconsistency of Palamecia 7F teleport blocking, the battle background for Mysidia Cave B4, and the exit coordinates on the world map for the Mysidian Tower.

Jiggers

  • Sr. Member
  • ****
  • Posts: 405
    • View Profile
    • My Ko-Fi Page
Re: Final Fantasy II Restored
« Reply #398 on: June 15, 2020, 04:25:04 pm »
Yeah, this is just for metatiles. Still have to find exactly how many of those are in the game's data, then find out what graphic tiles they represent. But this doesn't contain any teleport coordinates or anything... so kind of useless if there's no bugs in the map layouts.  :P

The battle background will be in a table... it MAY be preceded by an "LDA $48" but I feel like its more likely that the value is one of the 16 bytes loaded at L1D66 (that's Mesen's debugger's label, not the disassembly's.) Or one of those bytes is used to look up the battle background from another table.

Battle backgrounds get loaded into $7600 RAM, so backtracking from where that's loaded during battle set up will be the easiest way to find the table. I'm in the process of doing that right now (got sidetracked from writing this post.)

I should be able to find the exit coordinates for the world map too, just by leaving/entering the town over and over.

What's the Palamecia 7F teleport blocking though?



Got into a battle on the overworld:
Code: [Select]
F3C75C:                 
  C75C  LDA $27      ; overworld scroll x or y           
  C75E  CLC                     
  C75F  ADC #$07     ; add 7 to get player position           
  C761  STA $80                 
  C763  LDA $28      ; overworld scroll x or y           
  C765  CLC                     
  C766  ADC #$07     ; add 7 to get player position           
  C768  AND #$0F                 
  C76A  ORA #$70                 
  C76C  STA $81      ; $80 is now a pointer to $765A - one step left in the bright grass outside the starting town's gate
  C76E  LDY #$00                 
  C770  LDA ($80),Y  ; gets the tile ID and puts it in Y           
  C772  TAY                     
  C773  ASL A        ; double tile ID and put in X
  C774  TAX                     
  C775  LDA $0400,X  ; get tile properties?             
  C778  AND #$10     ; cut out all bits but this 1           
  C77A  STA $43                 
  C77C  LDA #$00                 
  C77E  JSR F3FE03   ; swap to bank 0           
  C781  LDX $9500,Y  ; $9500 is a table with battle backdrop IDs?           
  C784  RTS          ; Y = $24 gets an ID of $02
             

Code: [Select]
L3FA9E:                 
  FA9E  STA $7B48               
  FAA1  TXA          ; X = backdrop ID?
  FAA2  AND #$0F     ; cut off high bits           
  FAA4  STA $7B49    ; save at $7B49           
  FAA7  JSR F3FA1F               

Code: [Select]
F2DFAE:                 
  9FAE  LDA $7B49   ; battle backdrop ID?             
  9FB1  AND #$07    ; cut off all bits except lowest 3             
  9FB3  CLC         ;             
  9FB4  ADC #$B8    ; add in the start of backdrop graphics             
  9FB6  STA $01     ; save as high byte of pointer             
  9FB8  LDA #$00                 
  9FBA  STA $00     ; $00 becomes the pointer to the backdrop graphics             
  9FBC  JSR F3FB53               

So this was for overworld stuff... That first code block will have a similar copy for dungeons. So watch out for writes to $7B49! If you need any more help, I could use a save state or save file somewhere other than the start of the game to better figure it out. Or just get up to the second town on my own in a bit.
« Last Edit: June 15, 2020, 05:29:58 pm by Jiggers »
I know exactly what I'm doing. I just don't know what effect it's going to have.

I wrote some NES music! Its a legal ROM file. - I got a Ko-Fi page too.

redmagejoe

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Final Fantasy II Restored
« Reply #399 on: June 15, 2020, 05:10:43 pm »
The entirety of Palamecia Castle, once entered, is supposed to prevent the player from escaping via Teleport or Warp, as is handled in many other places in the game "An energy field prevents you from warping out". This includes, apparently, most of 7F of the castle. However, there's an area in the center of 7F, which is accessed via a different set of stairs such that it's one floor but with two separate "areas" divided by walls, where it's completely possible to teleport out. I'm hard pressed to believe this was intentional, but I'd also think that it would be the entire floor that has a "no teleport" flag set.

If all maps simply have a yes/no flag for teleport, but these very specific tiles allow it, then I'd have to speculate it was intentional since it would be a unique behavior of the game. My current theory though is that maybe it's metatiles that have this characteristic by definition, sort of like they did in the Crystalis romhack I was working on, and by pure chance they happened to use tiles they shouldn't have. All of this is currently speculation until we can see precisely what's happening.