internal STFSDescriptor(byte[] xDescriptor, uint xTotalBlocks, uint xOldBlocks, byte xType)
 {
     xStruct = xDescriptor;
     XSetStructure((STFSType)(xType & 1));
     TopRecord = new BlockRecord(((uint)(xType >> 1) << 30 | (uint)xOldBlocks << 15));
     if (xTotalBlocks > SpaceBetween[2])
     {
         xStruct = null;
         return;
     }
     xBlockCount = xTotalBlocks;
     xBaseByte = (byte)((ThisType == STFSType.Type0) ? 0xB : 0xA);
     xOldBlocks = 0;
 }
예제 #2
0
 internal STFSDescriptor(byte[] xDescriptor, uint xTotalBlocks, uint xOldBlocks, byte xType)
 {
     xStruct = xDescriptor;
     XSetStructure((STFSType)(xType & 1));
     TopRecord = new BlockRecord(((uint)(xType >> 1) << 30 | (uint)xOldBlocks << 15));
     if (xTotalBlocks > SpaceBetween[2])
     {
         xStruct = null;
         return;
     }
     xBlockCount = xTotalBlocks;
     xBaseByte   = (byte)((ThisType == STFSType.Type0) ? 0xB : 0xA);
     xOldBlocks  = 0;
 }
 public static bool ContainsBlock(this List<BlockRecord> x, BlockRecord y)
 {
     foreach (BlockRecord z in x)
     {
         if (z.ThisBlock == y.ThisBlock)
             return true;
     }
     return false;
 }
        void SwitchNWrite(BlockRecord RecIn, SwitchType Change)
        {
            // As a temp, this will just grab the correct offset and write to it
            // I disabled the switch/backup effect in order to preserve functionality
            //
            // RECONSTRUCT
            //

            bool canswitch = (xSTFSStruct.ThisType == STFSType.Type1);
            //const uint basetable = 0xFFFFF000;
            BlockRecord current = xSTFSStruct.TopRecord;
            long[] pos = new long[] { 0, 0, 0 };
            // Grab base starting points
            if (RecIn.ThisBlock >= Constants.BlockLevel[0] ||
                xSTFSStruct.xBlockCount > Constants.BlockLevel[0])
            {
                if (RecIn.ThisBlock >= Constants.BlockLevel[1] ||
                    xSTFSStruct.xBlockCount > Constants.BlockLevel[1])
                    pos[0] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L2) + 0x14;
                pos[1] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L1) + 0x14;
            }
            pos[2] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L0) + 0x14;
            //bool wipe = current.BlocksFree >= (Constants.BlockLevel[1] * Constants.BlockLevel[0]);
            long len = GenerateDataOffset(RecIn.ThisBlock) + 0x1000;
            if (xIO.Length < len)
                xIO.SetLength(len);
            if (Change == SwitchType.Allocate)
                xSTFSStruct.TopRecord.BlocksFree--;
            else if (Change == SwitchType.Delete)
                xSTFSStruct.TopRecord.BlocksFree++;
            if (pos[0] != 0)
            {
                //if (wipe)
                //{
                //    xIO.Position = (pos[0] & basetable) + (current.Index << 0xC);
                //    xIO.Write(new byte[0x1000]);
                //    xIO.Flush();
                //}
                /*if (canswitch) // If this table hasn't been switched yet
                {
                    if (!switched2)
                    {
                        xIO.Position = (pos[0] & basetable) + (current.Index << 0xC); // Get starting of table
                        byte[] data = xIO.ReadBytes(0x1000); // Read it
                        xSTFSStruct.TopRecord.Switch(); // Switch the index
                        pos[0] += (xSTFSStruct.TopRecord.Index << 0xC); // Add to the base STFS function result
                        xIO.Position = (pos[0] & basetable); // Go to new position and write it
                        xIO.Write(data);
                        xIO.Flush();
                        data = null;
                        switched2 = true;
                    }
                    else pos[0] += (current.Index << 0xC); // Already switched, add the index
                }*/

                //KILL ON RECONSTRUCTION
                if (canswitch)
                    pos[0] += (current.Index << 0xC);
                // ---------------------

                xIO.Position = pos[0];
                current = new BlockRecord(xIO.ReadUInt32());
                //wipe = current.BlocksFree >= Constants.BlockLevel[1];
                if (Change != SwitchType.None)
                {
                    if (Change == SwitchType.Allocate)
                        current.BlocksFree--; // Takes away a free block
                    else current.BlocksFree++; // Adds a free block
                    xIO.Position = pos[0];
                    xIO.Write(current.Flags);
                    xIO.Flush();
                }
            }
            // Follows same pattern
            if (pos[1] != 0)
            {
                //if (wipe)
                //{
                //    xIO.Position = (pos[1] & basetable) + (current.Index << 0xC);
                //    xIO.Write(new byte[0x1000]);
                //    xIO.Flush();
                //}
                /*if (canswitch)
                {
                    if (!switched1.Contains((int)(RecIn.ThisBlock / Constants.BlockLevel[1])))
                    {
                        xIO.Position = (pos[1] & basetable) + (current.Index << 0xC);
                        byte[] data = xIO.ReadBytes(0x1000);
                        current.Switch();
                        pos[1] += (current.Index << 0xC);
                        xIO.Position = (pos[1] & basetable);
                        xIO.Write(data);
                        xIO.Flush();
                        data = null;
                        if (pos[0] != 0)
                        {
                            xIO.Position = pos[0];
                            xIO.Write(current.Flags);
                            xIO.Flush();
                        }
                        switched1.Add((int)(RecIn.ThisBlock / Constants.BlockLevel[1]));
                        if (xSTFSStruct.xBlockCount <= Constants.BlockLevel[1])
                            xSTFSStruct.TopRecord.Switch();
                    }
                    else pos[1] += (current.Index << 0xC);
                }*/

                //KILL ON RECONSTRUCTION
                if (canswitch)
                    pos[1] += (current.Index << 0xC);
                // ---------------------

                xIO.Position = pos[1];
                current = new BlockRecord(xIO.ReadUInt32());
                //wipe = current.BlocksFree >= Constants.BlockLevel[0];
                if (Change != SwitchType.None)
                {
                    if (Change == SwitchType.Allocate)
                        current.BlocksFree--; // Takes away a free block
                    else current.BlocksFree++; // Adds a free block
                    xIO.Position = pos[1];
                    xIO.Write(current.Flags);
                    xIO.Flush();
                }
            }
            //if (wipe)
            //{
            //    xIO.Position = (pos[0] & basetable) + (current.Index << 0xC);
            //    xIO.Write(new byte[0x1000]);
            //    xIO.Flush();
            //}
            /*if (canswitch)
            {
                if (!switched0.Contains((int)(RecIn.ThisBlock / Constants.BlockLevel[0])))
                {
                    xIO.Position = (pos[2] & basetable) + (current.Index << 0xC);
                    byte[] data = xIO.ReadBytes(0x1000);
                    current.Switch();
                    pos[2] += (current.Index << 0xC);
                    xIO.Position = (pos[2] & basetable);
                    xIO.Write(data);
                    xIO.Flush();
                    data = null;
                    if (pos[1] != 0)
                    {
                        xIO.Position = pos[1];
                        xIO.Write(current.Flags);
                        xIO.Flush();
                    }
                    switched1.Add((int)(RecIn.ThisBlock / Constants.BlockLevel[0]));
                    if (xSTFSStruct.xBlockCount <= Constants.BlockLevel[0])
                        xSTFSStruct.TopRecord.Switch();
                }
                else pos[2] += (current.Index << 0xC);
            }*/

            //KILL ON RECONSTRUCTION
            if (canswitch)
                pos[2] += (current.Index << 0xC);
            // ---------------------

            if (Change == SwitchType.Allocate)
            {
                if (RecIn.Status == HashStatus.Old)
                    RecIn.Status = HashStatus.Reused;
                else RecIn.Status = HashStatus.New;
            }
            else if (Change == SwitchType.Delete)
                RecIn.MarkOld();
            xIO.Position = pos[2];
            xIO.Write(RecIn.Flags);
            xIO.Flush();
            if (RecIn.ThisBlock >= xSTFSStruct.xBlockCount)
                xSTFSStruct.xBlockCount = RecIn.ThisBlock + 1;
        }
 BlockRecord GetRecord(uint xBlock, TreeLevel xLevel)
 {
     if (xLevel == TreeLevel.LT)
         return xSTFSStruct.TopRecord;
     BlockRecord current = xSTFSStruct.TopRecord;
     bool canswitch = (xSTFSStruct.ThisType == STFSType.Type1);
     if (xSTFSStruct.xBlockCount > Constants.BlockLevel[1])
     {
         // Grab base position
         xIO.Position = (xSTFSStruct.GenerateHashOffset(xBlock, TreeLevel.L2) + 0x14);
         if (canswitch)
             xIO.Position += (current.Index << 0xC);
         current = new BlockRecord(xIO.ReadUInt32()); // Read new flag
         if (xLevel == TreeLevel.L2)
         {
             // return if needed
             current.ThisBlock = xBlock;
             current.ThisLevel = TreeLevel.L2;
             return current;
         }
     }
     else if (xLevel == TreeLevel.L2)
         return xSTFSStruct.TopRecord;
     // Follows same procedure
     if (xSTFSStruct.xBlockCount > Constants.BlockLevel[0])
     {
         xIO.Position = (xSTFSStruct.GenerateHashOffset(xBlock, TreeLevel.L1)) + 0x14;
         if (canswitch)
             xIO.Position += (current.Index << 0xC);
         current = new BlockRecord(xIO.ReadUInt32());
         if (xLevel == TreeLevel.L1)
         {
             current.ThisBlock = xBlock;
             current.ThisLevel = TreeLevel.L1;
             return current;
         }
     }
     else if (xLevel == TreeLevel.L1)
         return xSTFSStruct.TopRecord;
     xIO.Position = (xSTFSStruct.GenerateHashOffset(xBlock, TreeLevel.L0)) + 0x14;
     if (canswitch)
         xIO.Position += (current.Index << 0xC);
     current = new BlockRecord(xIO.ReadUInt32());
     current.ThisBlock = xBlock;
     current.ThisLevel = TreeLevel.L0;
     return current;
 }
 /// <summary>
 /// Writes a file via blocks
 /// </summary>
 /// <param name="xIOIn"></param>
 /// <param name="xBlocks"></param>
 /// <returns></returns>
 internal bool xWriteTo(ref DJsIO xIOIn, BlockRecord[] xBlocks)
 {
     if (!xIOIn.Accessed || (xIOIn.BlockCountSTFS() != xBlocks.Length))
         return false;
     try
     {
         xIOIn.Position = 0;
         for (int i = 0; i < xBlocks.Length - 1; i++)
         {
             // Finds spot and writes block of data
             xIO.Position = GenerateDataOffset(xBlocks[i].ThisBlock);
             xIO.Write(xIOIn.ReadBytes(0x1000));
         }
         xIO.Position = GenerateDataOffset(xBlocks[xBlocks.Length - 1].ThisBlock);
         xIO.Write(xIOIn.ReadBytes(xIOIn.BlockRemainderSTFS()));
         xIO.Flush();
         return true;
     }
     catch { return false; }
 }
 internal bool xWriteChain(BlockRecord[] xRecs)
 {
     for (int i = 0; i < xRecs.Length; i++)
     {
         if ((i + 1) < xRecs.Length)
             xRecs[i].NextBlock = xRecs[i + 1].ThisBlock;
         else xRecs[i].NextBlock = Constants.STFSEnd;
         SwitchNWrite(xRecs[i], SwitchType.Allocate);
     }
     return true;
 }
 /// <summary>
 /// Add a file to the package
 /// </summary>
 /// <param name="xIOIn"></param>
 /// <param name="xEntAlloc"></param>
 /// <param name="xFileAlloc"></param>
 /// <returns></returns>
 internal bool xDoAdd(ref DJsIO xIOIn, ref BlockRecord[] xEntAlloc, ref BlockRecord[] xFileAlloc)
 {
     // Gets Entry Table file
     DJsIO xEntFile;
     if (!xEntriesToFile(out xEntFile))
         return (xActive = false);
     // Writes it
     AddToLog("Adding new entry table to package");
     if (!xWriteTo(ref xEntFile, xEntAlloc))
     {
         xEntFile.Close();
         VariousFunctions.DeleteFile(xEntFile.FileNameLong);
         return (xActive = false);
     }
     xEntFile.Close();
     VariousFunctions.DeleteFile(xEntFile.FileNameLong);
     // Writes the new file
     AddToLog("Writing file to package");
     if (!xWriteTo(ref xIOIn, xFileAlloc))
         return (xActive = false);
     if (!xWriteChain(xEntAlloc))
         return (xActive = false);
     if (!xWriteChain(xFileAlloc))
         return (xActive = false);
     // Fixes internal variables and then writes hashes
     AddToLog("Fixing Package variables");
     xDeleteChain(xFileBlocks);
     xFileBlocks = xEntAlloc;
     xSTFSStruct.xDirectoryBlock = xEntAlloc[0].ThisBlock;
     foreach (FileEntry x in xFileDirectory)
         x.xFixOffset();
     foreach (FolderEntry x in xFolderDirectory)
         x.xFixOffset();
     xWriteDescriptor(ref xIO);
     return !(xActive = false);
 }
 internal bool xDeleteChain(BlockRecord[] xBlocks)
 {
     if (xBlocks == null)
         return true;
     foreach (BlockRecord x in xBlocks)
     {
         SwitchNWrite(x, SwitchType.Delete);
     }
     return true;
 }
 internal BlockRecord[] xAllocateBlocks(uint count, uint xStart)
 {
     if ((xSTFSStruct.BlockCount + count) > xSTFSStruct.SpaceBetween[2])
         return new BlockRecord[0];
     List<BlockRecord> xReturn = new List<BlockRecord>();
     for (uint i = 0; i < count; i++)
     {
         BlockRecord x = null;
         while (x == null)
         {
             if (xStart > xSTFSStruct.SpaceBetween[2])
                 break;
             // Grab record or make new one
             if (xStart < xSTFSStruct.xBlockCount)
             {
                 BlockRecord y = GetRecord(xStart, TreeLevel.L0);
                 if (y.Status == HashStatus.Old || y.Status == HashStatus.Unused)
                     x = y;
             }
             else
             {
                 if (xStart == Constants.BlockLevel[0])
                 {
                     xIO.Position = GenerateHashOffset(0, TreeLevel.L1) + (xSTFSStruct.TopRecord.Index << 0xC) + 0x14;
                     xIO.Write(xSTFSStruct.TopRecord.Flags);
                     xIO.Flush();
                 }
                 else if (xStart == Constants.BlockLevel[1])
                 {
                     xIO.Position = GenerateHashOffset(0, TreeLevel.L2) + (xSTFSStruct.TopRecord.Index << 0xC) + 0x14;
                     xIO.Write(xSTFSStruct.TopRecord.Flags);
                     xIO.Flush();
                 }
                 x = new BlockRecord(HashStatus.New, Constants.STFSEnd);
                 x.ThisBlock = xStart;
                 x.ThisLevel = TreeLevel.L0;
             }
             xStart++;
         }
         xReturn.Add(x);
     }
     return xReturn.ToArray();
 }
 /// <summary>
 /// Returns the blocks of a file
 /// </summary>
 /// <param name="xCount"></param>
 /// <param name="xStartBlock"></param>
 /// <param name="xOutBlocks"></param>
 /// <returns></returns>
 internal bool GetBlocks(uint xCount, uint xStartBlock, out BlockRecord[] xOutBlocks)
 {
     // Follows the blocks for the specified max count
     List<BlockRecord> xBlockList = new List<BlockRecord>();
     BlockRecord xBlock = GetRecord(xStartBlock, TreeLevel.L0);
     if (xBlock.ThisBlock >= xSTFSStruct.xBlockCount)
         throw STFSExcepts.InvalBlock;
     for (uint i = 0; i < xCount; i++)
     {
         if (!xBlockList.ContainsBlock(xBlock))
             xBlockList.Add(xBlock);
         else break; // If it contains, it's just going to loop
         if (xBlock.NextBlock == Constants.STFSEnd)
             break; // Stop means stop
         if (xBlock.NextBlock >= xSTFSStruct.xBlockCount)
             throw STFSExcepts.InvalBlock;
         // Gets the next block record
         xBlock = GetRecord(xBlock.NextBlock, TreeLevel.L0);
     }
     xOutBlocks = xBlockList.ToArray();
     // Success if 1 - end block is reached and 2 - count is the count of the blocks found
     return (xBlockList.Count == xCount);
 }
 internal STFSDescriptor(STFSPackage xPackage)
 {
     xPackage.xIO.Position = 0x340;
     xPackage.xIO.IsBigEndian = true;
     int xBlockInfo = xPackage.xIO.ReadInt32();
     xBaseByte = (byte)(((xBlockInfo + 0xFFF) & 0xF000) >> 0xC);
     xPackage.xIO.Position = 0x379;
     if (xPackage.xIO.ReadByte() != 0x24) // Struct Size
         throw STFSExcepts.Type;
     if (xPackage.xIO.ReadByte() != 0) // Reversed
         throw STFSExcepts.Type;
     /* STRUCT OF THE NEXT 6 BYTES:
      * byte for block separation
      * Little Endian File Table block count short (2 bytes)
      * 3 bytes in Little Endian for the starting block of the File Table */
     byte idx = (byte)(xPackage.xIO.ReadByte() & 3);
     xStruct = xPackage.xIO.ReadBytes(5);
     xPackage.xIO.Position = 0x395;
     xBlockCount = xPackage.xIO.ReadUInt32();
     uint xOldBlocks = xPackage.xIO.ReadUInt32();
     // Checks the type of Structure
     if (xBaseByte == 0xB)
     {
         if (idx == 1)
             XSetStructure(STFSType.Type0);
         else
             throw STFSExcepts.Type;
     }
     else if (xBaseByte == 0xA)
     {
         if (idx == 0 || idx == 2)
             XSetStructure(STFSType.Type1);
         else
             throw STFSExcepts.Type;
     }
     else
         throw STFSExcepts.Type;
     if (xBlockCount > SpaceBetween[2])
         throw STFSExcepts.MaxOver;
     TopRecord = new BlockRecord(((uint)((idx >> 1) & 1) << 30 | (uint)xOldBlocks << 15));
     // Grab Real Block Count
     for (uint i = (xBlockCount - 1); i >= 0; i--)
     {
         xBlockCount = (i + 1);
         if (GenerateDataOffset(i) < xPackage.xIO.Length)
             break;
     }
 }
예제 #13
0
        internal STFSDescriptor(STFSPackage xPackage)
        {
            xPackage.xIO.Position    = 0x340;
            xPackage.xIO.IsBigEndian = true;
            int xBlockInfo = xPackage.xIO.ReadInt32();

            xBaseByte             = (byte)(((xBlockInfo + 0xFFF) & 0xF000) >> 0xC);
            xPackage.xIO.Position = 0x379;
            if (xPackage.xIO.ReadByte() != 0x24) // Struct Size
            {
                throw STFSExcepts.Type;
            }
            if (xPackage.xIO.ReadByte() != 0) // Reversed
            {
                throw STFSExcepts.Type;
            }

            /* STRUCT OF THE NEXT 6 BYTES:
             * byte for block separation
             * Little Endian File Table block count short (2 bytes)
             * 3 bytes in Little Endian for the starting block of the File Table */
            byte idx = (byte)(xPackage.xIO.ReadByte() & 3);

            xStruct = xPackage.xIO.ReadBytes(5);
            xPackage.xIO.Position = 0x395;
            xBlockCount           = xPackage.xIO.ReadUInt32();
            uint xOldBlocks = xPackage.xIO.ReadUInt32();

            // Checks the type of Structure
            if (xBaseByte == 0xB)
            {
                if (idx == 1)
                {
                    XSetStructure(STFSType.Type0);
                }
                else
                {
                    throw STFSExcepts.Type;
                }
            }
            else if (xBaseByte == 0xA)
            {
                if (idx == 0 || idx == 2)
                {
                    XSetStructure(STFSType.Type1);
                }
                else
                {
                    throw STFSExcepts.Type;
                }
            }
            else
            {
                throw STFSExcepts.Type;
            }
            if (xBlockCount > SpaceBetween[2])
            {
                throw STFSExcepts.MaxOver;
            }
            TopRecord = new BlockRecord(((uint)((idx >> 1) & 1) << 30 | (uint)xOldBlocks << 15));
            // Grab Real Block Count
            for (uint i = (xBlockCount - 1); i >= 0; i--)
            {
                xBlockCount = (i + 1);
                if (GenerateDataOffset(i) < xPackage.xIO.Length)
                {
                    break;
                }
            }
        }
        void SwitchNWrite(BlockRecord RecIn, SwitchType Change)
        {
            bool canswitch = (xSTFSStruct.ThisType == STFSType.Type1);

            BlockRecord current = xSTFSStruct.TopRecord;
            long[] pos = new long[] { 0, 0, 0 };
            // Grab base starting points
            if (RecIn.ThisBlock >= Constants.BlockLevel[0] ||
                xSTFSStruct.xBlockCount > Constants.BlockLevel[0])
            {
                if (RecIn.ThisBlock >= Constants.BlockLevel[1] ||
                    xSTFSStruct.xBlockCount > Constants.BlockLevel[1])
                    pos[0] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L2) + 0x14;
                pos[1] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L1) + 0x14;
            }
            pos[2] = xSTFSStruct.GenerateHashOffset(RecIn.ThisBlock, TreeLevel.L0) + 0x14;

            long len = GenerateDataOffset(RecIn.ThisBlock) + 0x1000;
            if (xIO.Length < len)
                xIO.SetLength(len);
            if (Change == SwitchType.Allocate)
                xSTFSStruct.TopRecord.BlocksFree--;
            else if (Change == SwitchType.Delete)
                xSTFSStruct.TopRecord.BlocksFree++;
            if (pos[0] != 0)
            {
                if (canswitch)
                    pos[0] += (current.Index << 0xC);
                // ---------------------

                xIO.Position = pos[0];
                current = new BlockRecord(xIO.ReadUInt32());

                if (Change != SwitchType.None)
                {
                    if (Change == SwitchType.Allocate)
                        current.BlocksFree--; // Takes away a free block
                    else
                        current.BlocksFree++; // Adds a free block
                    xIO.Position = pos[0];
                    xIO.Write(current.Flags);
                    xIO.Flush();
                }
            }
            // Follows same pattern
            if (pos[1] != 0)
            {

                if (canswitch)
                    pos[1] += (current.Index << 0xC);
                // ---------------------

                xIO.Position = pos[1];
                current = new BlockRecord(xIO.ReadUInt32());

                if (Change != SwitchType.None)
                {
                    if (Change == SwitchType.Allocate)
                        current.BlocksFree--; // Takes away a free block
                    else
                        current.BlocksFree++; // Adds a free block
                    xIO.Position = pos[1];
                    xIO.Write(current.Flags);
                    xIO.Flush();
                }
            }

            if (canswitch)
                pos[2] += (current.Index << 0xC);
            // ---------------------

            if (Change == SwitchType.Allocate)
            {
                if (RecIn.Status == HashStatus.Old)
                    RecIn.Status = HashStatus.Reused;
                else
                    RecIn.Status = HashStatus.New;
            }
            else if (Change == SwitchType.Delete)
                RecIn.MarkOld();
            xIO.Position = pos[2];
            xIO.Write(RecIn.Flags);
            xIO.Flush();
            if (RecIn.ThisBlock >= xSTFSStruct.xBlockCount)
                xSTFSStruct.xBlockCount = RecIn.ThisBlock + 1;
        }
        internal bool xWriteTo(MemoryStream ms, BlockRecord[] xBlocks)
        {
            //try
            {

                ms.Seek(0, SeekOrigin.Begin);
                var br = new BinaryReader(ms);

                for (int i = 0; i < xBlocks.Length - 1; i++)
                {
                    // Finds spot and writes block of data
                    xIO.Position = GenerateDataOffset(xBlocks[i].ThisBlock);
                    var b = br.ReadBytes(0x1000);
                    xIO.Write(b);
                }
                xIO.Position = GenerateDataOffset(xBlocks[xBlocks.Length - 1].ThisBlock);
                var remainder = BlockRemainderSTFS(ms.Length);
                var b2 = br.ReadBytes(remainder);
                xIO.Write(b2);
                xIO.Flush();
                return true;
            }
            //catch { return false; }
        }