Exemple #1
0
        public static byte[] Chunk(List <byte[]> input)
        {
            var ms = new System.IO.MemoryStream();

            byte[] scratch = new byte[4];
            ms.Write(scratch, 0, 2);
            ms.Write(BitConverter.GetBytes(input.Count), 0, 4);
            int offset = 0x2A;

            foreach (var s in input)
            {
                Bytes.WriteInt(ms, offset);
                offset += 4;
                offset += s.Length;
            }
            foreach (var s in input)
            {
                Bytes.WriteInt(ms, s.Length);
                ms.Write(s, 0, s.Length);
            }
            ms.Position = 0;
            var compress = new System.IO.MemoryStream();

            Lzs.Encode(ms, compress);
            byte[] data = new byte[compress.Length + 4];
            compress.Position = 0;
            compress.Read(data, 4, (int)compress.Length);
            Bytes.WriteInt(data, 0, (int)compress.Length);
            return(data);
        }
Exemple #2
0
 public VRangeChunked(string name, List <RuntimeMod> mods, IntPtr fallbackHandle, uint fallbackOffset, int fallbackLen)
 {
     _mods     = mods;
     _fbHandle = fallbackHandle;
     _fbOffset = fallbackOffset;
     _fbLen    = fallbackLen;
     _header   = new byte[24];
     byte[] bname = System.Text.Encoding.ASCII.GetBytes(name);
     Array.Copy(bname, _header, bname.Length);
     Bytes.WriteInt(_header, 20, _fbLen);
 }
Exemple #3
0
 public VRangeConditional(string name, List <OverrideFile> files, IntPtr fallbackHandle, uint fallbackOffset)
 {
     _files          = files;
     _handle         = IntPtr.Zero;
     _current        = null;
     _header         = new byte[24];
     _fallbackHandle = fallbackHandle;
     _fallbackOffset = fallbackOffset;
     byte[] bname = System.Text.Encoding.ASCII.GetBytes(name);
     Array.Copy(bname, _header, bname.Length);
     Bytes.WriteInt(_header, 20, files.Select(f => f.Size).Max());
 }
Exemple #4
0
        private unsafe void Recalculate()
        {
            DebugLogger.WriteLine($"Chunked file {Name} recalculating contents...");
            byte[]           original = new byte[_fbLen];
            Win32.OVERLAPPED ov       = new Win32.OVERLAPPED()
            {
                EventHandle  = IntPtr.Zero,
                Internal     = UIntPtr.Zero,
                InternalHigh = UIntPtr.Zero,
                Offset       = _fbOffset,
                OffsetHigh   = 0
            };

            fixed(byte *bp = &original[0])
            {
                uint bytesRead = 0;

                //TODO should loop...
                Win32.ReadFile(_fbHandle, new IntPtr(bp), (uint)_fbLen, ref bytesRead, ref ov);
            }

            DebugLogger.WriteLine($"Original read {_fbLen} from {_fbOffset} sig {original[0]} {original[1]} {original[2]} {original[3]}");

            var orig = FieldFile.Unchunk(original);

            foreach (int i in Enumerable.Range(0, orig.Count))
            {
                string fn = Name + ".chunk." + (i + 1);
                foreach (var of in _mods.SelectMany(m => m.GetOverrides(fn)))
                {
                    if (of.CFolder == null || of.CFolder.IsActive(of.CName))
                    {
                        if (of.Archive == null)
                        {
                            orig[i] = System.IO.File.ReadAllBytes(of.File);
                        }
                        else
                        {
                            orig[i] = of.Archive.GetBytes(of.File);
                        }
                        break;
                    }
                }
            }

            _calculated = FieldFile.Chunk(orig);
            Bytes.WriteInt(_header, 20, _calculated.Length);
            DebugLogger.WriteLine($"New length of {Name} is {_calculated.Length}");
        }
Exemple #5
0
        public static byte[] CalculateHeaders(List <LGPEntry> files, Func <string, int> headerSortKey, Func <string, uint> dataSortKey, out List <LGPEntryMade> entries)
        {
            files = files.OrderBy(e => e.HashCode).ThenBy(e => headerSortKey(e.Name)).ToList();
            byte[] hash   = new byte[LGPEntry.HashValues * LGPEntry.HashValues * 4];
            TOC[]  toc    = new TOC[files.Count];
            var    hfiles = files.GroupBy(e => e.HashCode).OrderBy(g => g.Key);

            List <List <PathEntry> > paths = new List <List <PathEntry> >();

            entries = new List <LGPEntryMade>();

            int count = 0;

            //int position = 0;
            foreach (var group in hfiles)
            {
                Bytes.WriteUShort(hash, 4 * group.Key, (ushort)(count + 1));
                Bytes.WriteUShort(hash, 4 * group.Key + 2, (ushort)(group.Count()));

                foreach (var name in group.OfType <LGPEntry>().GroupBy(e => e.TOCName).OrderBy(g => headerSortKey(g.Key)))
                {
                    bool hasPaths = name.Count() > 1;
                    if (hasPaths)
                    {
                        paths.Add(new List <PathEntry>());
                    }

                    foreach (var file in name)
                    {
                        toc[count]        = new TOC(file.TOCName);
                        toc[count].Type   = 14;
                        toc[count].Path   = (ushort)(hasPaths ? paths.Count : 0);
                        toc[count].Source = file;
                        //toc[count].Offset = position; //just use file sizes so far, we'll calculate the additional offset due to header later - once the file paths are done
                        //position += 24 + file.MaxSize;
                        if (hasPaths)
                        {
                            paths.Last().Add(new PathEntry()
                            {
                                Index = (ushort)count, Path = file.Path
                            });
                        }
                        entries.Add(new LGPEntryMade()
                        {
                            Entry = file, TOCIndex = count
                        });
                        count++;
                    }
                }
            }

            int headerSize = 16                                           //initial header
                             + (27 * toc.Length)                          //toc
                             + hash.Length                                //hashtable
                             + 2                                          //path count
                             + paths.Select(L => 2 + L.Count * 130).Sum() //path entries - 2 byte count for each list, followed by 130 bytes per entry
            ;

            int position = 0;

            count = 0;
            foreach (var em in entries.OrderBy(em => dataSortKey(em.Entry.Name)).ThenBy(em => em.Entry.Name))
            {
                em.DataOffset = toc[em.TOCIndex].Offset = position + headerSize;
                em.DataIndex  = count;
                position     += 24 + em.Entry.MaxSize;
                count++;
            }

            byte[] header = new byte[headerSize];
            //Initial header
            Array.Copy(System.Text.Encoding.ASCII.GetBytes("SQUARESOFT"), 0, header, 2, 10);
            Bytes.WriteInt(header, 12, toc.Length);
            //Now write TOC
            int offset = 16;

            foreach (var entry in toc)
            {
                Array.Copy(entry.Name, 0, header, offset, entry.Name.Length);
                offset += 20;
                Bytes.WriteInt(header, offset, entry.Offset);
                offset        += 4;
                header[offset] = entry.Type;
                offset++;
                Bytes.WriteUShort(header, offset, entry.Path);
                offset += 2;
            }
            //Now hash table
            Array.Copy(hash, 0, header, offset, hash.Length);
            offset += hash.Length;
            //Now path array...
            Bytes.WriteUShort(header, offset, (ushort)(paths.Count));
            offset += 2;
            foreach (var pathlist in paths)
            {
                Bytes.WriteUShort(header, offset, (ushort)(pathlist.Count));
                offset += 2;
                foreach (var path in pathlist)
                {
                    byte[] p = System.Text.Encoding.ASCII.GetBytes(path.Path);
                    Array.Copy(p, 0, header, offset, p.Length);
                    offset += 128;
                    Bytes.WriteUShort(header, offset, path.Index);
                    offset += 2;
                }
            }

            return(header);
        }
Exemple #6
0
        public override void Read(uint offset, uint length, IntPtr dest, ref uint bytesRead)
        {
            //DebugLogger.WriteLine("Conditional {2} reading from OS {0} L {1}", offset, length, Name);

            bool header = (offset < 24);
            bool init   = (offset == 24);

            if ((!_lastHeader && header) || (init && !_lastInit))   //re-evaluate
            {
                _current = null;
                if (!_handle.Equals(IntPtr.Zero))
                {
                    Win32.CloseHandle(_handle);
                }
                _handle = IntPtr.Zero;

                foreach (var of in _files)
                {
                    if (of.CFolder == null || of.CFolder.IsActive(of.CName))
                    {
                        DebugLogger.WriteLine($"Conditional {Name} switching to {of.File}");
                        _current = of;
                        Bytes.WriteInt(_header, 20, of.Size);
                        break;
                    }
                }
                if (_current == null)
                {
                    DebugLogger.WriteLine($"Conditional {Name} switching to fallback");
                }
                _lastInit = true; //we're ready to read file headers
            }
            else
            {
                _lastInit = init;
            }
            if (_current != null && _handle.Equals(IntPtr.Zero) && _current.Archive == null)
            {
                _handle = Wrap.CreateFileW(_current.File, System.IO.FileAccess.Read, System.IO.FileShare.Read, IntPtr.Zero, System.IO.FileMode.Open, System.IO.FileAttributes.Normal, IntPtr.Zero);
            }
            _lastHeader = header;
            _access     = DateTime.Now;

            if (_current == null)   //read from fallback
            //DebugLogger.WriteLine("Conditional reading from fallback handle {0} with extra offset {1}", _fallbackHandle, _fallbackOffset);
            {
                Win32.OVERLAPPED ov = new Win32.OVERLAPPED()
                {
                    EventHandle  = IntPtr.Zero,
                    Internal     = UIntPtr.Zero,
                    InternalHigh = UIntPtr.Zero,
                    Offset       = _fallbackOffset + offset,
                    OffsetHigh   = 0
                };
                Win32.ReadFile(_fallbackHandle, dest, length, ref bytesRead, ref ov);
                //DebugLogger.WriteLine("Conditional {1} reading from fallback - {0} bytes read", bytesRead, Name);
            }
            else
            {
                if (offset < 24)
                {
                    length = Math.Min(length, 24 - offset);
                    System.Runtime.InteropServices.Marshal.Copy(_header, (int)offset, dest, (int)length);
                    bytesRead = length;
                    //DebugLogger.WriteLine("Conditional {2} reading from cheader - {0} bytes read [current size is {1}]", bytesRead, BitConverter.ToInt32(_header, 20), Name);
                    return;
                }
                else
                {
                    offset -= 24;
                    if (_current.Archive == null)
                    {
                        Wrap.SetFilePointer(_handle, (int)offset, IntPtr.Zero, Wrap.EMoveMethod.Begin);
                        Win32.ReadFile(_handle, dest, length, ref bytesRead, IntPtr.Zero);
                        //DebugLogger.WriteLine("Conditional {1} reading from cfile - {0} bytes read", bytesRead, Name);
                    }
                    else
                    {
                        _current.Archive.RawRead(_current.File, offset, length, dest, ref bytesRead);
                        //DebugLogger.WriteLine("Conditional {1} reading from cfile archive offset {2} length {3} - {0} bytes read", bytesRead, Name, offset, length);
                    }
                }
            }
        }