• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
May 31, 2024, 05:37:12 am

News:

Don't be hasty to start your own mod; all our FFT modding projects are greatly understaffed! Find out how you can help in the Recruitment section or our Discord!


Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Goladus

1
Hi, just want to compliment you all on what a great forum you have here.  FFT was my favorite game for a long time.  I hope you'll indulge my question.

Is there a comprehensive map of all the data structures in SCUS_942.21 and the ENTD files?  What I'm looking for would be similar to what's on the wiki for World Stats: http://ffhacktics.com/wiki/World_Stats.

I am writing a command-line tool to query game data from the ISO and am assembling the data.  I was able to extract the basic structure from the FFTPatcher source code (https://github.com/Glain/FFTPatcher/blob/master/PatcherLib/ISOPatching/PsxIso.cs), most of which is also on the wiki (http://ffhacktics.com/wiki/CD_Full_Index) but I'm trying to figure out how data is laid out within the individual files.

The FFTPatcher source should have all of the individual data structures, but it looks like it's fairly heavily baked into the C# source code and not easy to extract with some simple text munging.  FFTPatcher credits ZodiacFFTM's excel spreadsheets, but I am unable to find these.

This:
static PsxIso()
        {
            Propositions = new KnownPosition( Sectors.WORLD_WLDCORE_BIN, 0x36380, 0xA7C );
            Abilities = new KnownPosition( Sectors.SCUS_942_21, 0x4F3F0, 9414 );
            AbilityEffects = new KnownPosition( Sectors.BATTLE_BIN, 0x14F3F0, 0x2E0 );
            ItemAbilityEffects = new KnownPosition( Sectors.BATTLE_BIN, 0x14F6D0, 0x1C );
            ReactionAbilityEffects = new KnownPosition( Sectors.BATTLE_BIN, 0x014F73C, 0x40 );
            ActionEvents = new KnownPosition( Sectors.SCUS_942_21, 0x564B4, 224 );
            InflictStatuses = new KnownPosition( Sectors.SCUS_942_21, 0x547C4, 0x300 );
            Jobs = new KnownPosition( Sectors.SCUS_942_21, 0x518B8, 0x1E00 );
            JobLevels = new KnownPosition( Sectors.SCUS_942_21, 0x568C4, 0xD0 );
            MonsterSkills = new KnownPosition( Sectors.SCUS_942_21, 0x563C4, 0xF0 );
            OldItemAttributes = new KnownPosition( Sectors.SCUS_942_21, 0x54AC4, 0x7D0 );
            OldItems = new KnownPosition( Sectors.SCUS_942_21, 0x536B8, 0x110A );
            PoachProbabilities = new KnownPosition( Sectors.SCUS_942_21, 0x56864, 0x60 );
            StatusAttributes = new KnownPosition( Sectors.SCUS_942_21, 0x565E4, 0x280 );
            SkillSets = new KnownPosition( Sectors.SCUS_942_21, 0x55294, 0x1130 );
            ENTD1 = new KnownPosition( Sectors.BATTLE_ENTD1_ENT, 0, 81920 );
            ENTD2 = new KnownPosition( Sectors.BATTLE_ENTD2_ENT, 0, 81920 );
            ENTD3 = new KnownPosition( Sectors.BATTLE_ENTD3_ENT, 0, 81920 );
            ENTD4 = new KnownPosition( Sectors.BATTLE_ENTD4_ENT, 0, 81920 );
            MoveFindItems = new KnownPosition( Sectors.BATTLE_BIN, 0x8EE74, 0x800 );
            StoreInventories = new KnownPosition( Sectors.WORLD_WORLD_BIN, 0xAD844, 0x200 );
            NumberOfSectorsBigEndian = new KnownPosition( (Sectors)16, 0x54, 4 );
            NumberOfSectorsLittleEndian = new KnownPosition( (Sectors)16, 0x50, 4 );

            // Ability animations go down until the Support abilities, so down up to and including 0x1C5 = 0x1C6 * 3 = 0x552 bytes
            AbilityAnimations = new KnownPosition( Sectors.BATTLE_BIN, 0x2CE10, 0x552 );
        }


Is easy enough to convert to this:


KnownPositions:
  Propositions: [WORLD_WLDCORE_BIN, 0x36380, 0xA7C]
  Abilities: [SCUS_942_21, 0x4F3F0, 9414]
  AbilityEffects: [BATTLE_BIN, 0x14F3F0, 0x2E0]
  ItemAbilityEffects: [BATTLE_BIN, 0x14F6D0, 0x1C]
  ReactionAbilityEffects: [BATTLE_BIN, 0x014F73C, 0x40]
  ActionEvents: [SCUS_942_21, 0x564B4, 224]
  InflictStatuses: [SCUS_942_21, 0x547C4, 0x300]
  Jobs: [SCUS_942_21, 0x518B8, 0x1E00]
  JobLevels: [SCUS_942_21, 0x568C4, 0xD0]
  MonsterSkills: [SCUS_942_21, 0x563C4, 0xF0]
  OldItemAttributes: [SCUS_942_21, 0x54AC4, 0x7D0]
  OldItems: [SCUS_942_21, 0x536B8, 0x110A]
  PoachProbabilities: [SCUS_942_21, 0x56864, 0x60]
  StatusAttributes: [SCUS_942_21, 0x565E4, 0x280]
  SkillSets: [SCUS_942_21, 0x55294, 0x1130]
  ENTD1: [BATTLE_ENTD1_ENT, 0, 81920]
  ENTD2: [BATTLE_ENTD2_ENT, 0, 81920]
  ENTD3: [BATTLE_ENTD3_ENT, 0, 81920]
  ENTD4: [BATTLE_ENTD4_ENT, 0, 81920]
  MoveFindItems: [BATTLE_BIN, 0x8EE74, 0x800]
  StoreInventories: [WORLD_WORLD_BIN, 0xAD844, 0x200]


But turning this into a simple data structure is going to be more of a hassle:


        public Job( Context context, byte value, string name, IList<byte> bytes, Job defaults )
        {
            Value = value;
            Name = name;
            int equipEnd = context == Context.US_PSP ? 13 : 12;

            SkillSet = context == Context.US_PSP ? SkillSet.PSPSkills[bytes[0]] : SkillSet.PSXSkills[bytes[0]];
            InnateA = AllAbilities.DummyAbilities[PatcherLib.Utilities.Utilities.BytesToUShort( bytes[1], bytes[2] )];
            InnateB = AllAbilities.DummyAbilities[PatcherLib.Utilities.Utilities.BytesToUShort( bytes[3], bytes[4] )];
            InnateC = AllAbilities.DummyAbilities[PatcherLib.Utilities.Utilities.BytesToUShort( bytes[5], bytes[6] )];
            InnateD = AllAbilities.DummyAbilities[PatcherLib.Utilities.Utilities.BytesToUShort( bytes[7], bytes[8] )];
            Equipment = new Equipment( bytes.Sub( 9, equipEnd ), defaults == null ? null : defaults.Equipment );
            HPConstant = bytes[equipEnd + 1];
            HPMultiplier = bytes[equipEnd + 2];
            MPConstant = bytes[equipEnd + 3];
            MPMultiplier = bytes[equipEnd + 4];
            SpeedConstant = bytes[equipEnd + 5];
            SpeedMultiplier = bytes[equipEnd + 6];
            PAConstant = bytes[equipEnd + 7];
            PAMultiplier = bytes[equipEnd + 8];
            MAConstant = bytes[equipEnd + 9];
            MAMultiplier = bytes[equipEnd + 10];
            Move = bytes[equipEnd + 11];
            Jump = bytes[equipEnd + 12];
            CEvade = bytes[equipEnd + 13];
            PermanentStatus = new Statuses( bytes.Sub( equipEnd + 14, equipEnd + 18 ), defaults == null ? null : defaults.PermanentStatus );
            StatusImmunity = new Statuses( bytes.Sub( equipEnd + 19, equipEnd + 23 ), defaults == null ? null : defaults.StatusImmunity );
            StartingStatus = new Statuses( bytes.Sub( equipEnd + 24, equipEnd + 28 ), defaults == null ? null : defaults.StartingStatus );
            AbsorbElement = new Elements( bytes[equipEnd + 29] );
            CancelElement = new Elements( bytes[equipEnd + 30] );
            HalfElement = new Elements( bytes[equipEnd + 31] );
            WeakElement = new Elements( bytes[equipEnd + 32] );

            MPortrait = bytes[equipEnd + 33];
            MPalette = bytes[equipEnd + 34];
            MGraphic = bytes[equipEnd + 35];

            if( defaults != null )
            {
                Default = defaults;
                AbsorbElement.Default = defaults.AbsorbElement;
                CancelElement.Default = defaults.CancelElement;
                HalfElement.Default = defaults.HalfElement;
                WeakElement.Default = defaults.WeakElement;
            }
        }


The ability code would be an even more complex example.  https://github.com/Glain/FFTPatcher/blob/master/Datatypes/Abilities/Ability.cs.

I'm just looking for a layout with offsets binary data types.  If this exists on the wiki and I'm just not seeing it, or if someone has the ZodiacFFTM spreadsheets that FFTPatcher was based on, I would be grateful if someone could point me in the right direction!

Thanks.