예제 #1
0
        public bool Redirect(ModDb modDb)
        {
            RedirectAttempted = true;

            foreach (var mod in modDb.Mods)
            {
                var pacRedirectFilePath = Path.Combine(mod.LoadDirectory, Pack.FileName, Native->Path);
                if (mod.Files.Contains(pacRedirectFilePath))
                {
                    // Replacement file stored in folder named after pac file
                    Redirect(pacRedirectFilePath);
                    mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {pacRedirectFilePath}");
                    return(true);
                }

                if (Pack.Cpk != null)
                {
                    var cpkRedirectFilePath = Path.Combine(mod.LoadDirectory, Pack.Cpk.FileName, Native->Path);
                    if (mod.Files.Contains(cpkRedirectFilePath))
                    {
                        // Replacement file stored in folder named after cpk file
                        Redirect(cpkRedirectFilePath);
                        mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {cpkRedirectFilePath}");
                        return(true);
                    }
                }

                mLogger.Debug($"No redirection for {Native->Path}.");
            }

            return(false);
        }
예제 #2
0
        private void ProcessWaveBankEntries(string filePath, VirtualSoundBank soundBank, VirtualWaveBank waveBank)
        {
            bool TryRedirectEntry(Mod mod, int i, string fileName)
            {
                var redirectFilePath = Path.Combine(Path.Combine(mod.LoadDirectory, "SND"), waveBank.FileName, fileName);

                if (File.Exists(redirectFilePath))
                {
                    if (waveBank.Entries[i].Redirect(redirectFilePath))
                    {
                        mLogger.Info($"{waveBank.FileName} Index: {i} Cue: {waveBank.Entries[i].CueName} redirected to {redirectFilePath}");
                    }
                    else
                    {
                        mLogger.Error($"{waveBank.FileName} Index: {i} Cue: {waveBank.Entries[i].CueName} redirecting to {redirectFilePath} failed!");
                    }

                    return(true);
                }

                return(false);
            }

            for (int i = 0; i < waveBank.Entries.Count; i++)
            {
                if (soundBank != null)
                {
                    waveBank.Entries[i].CueName = soundBank.GetTrackCueName(i, 0);
                }

                if (waveBank.Entries[i].IsRedirected)
                {
                    continue;
                }

                foreach (var mod in mModDb.Mods)
                {
                    // Try redirect from wave/track index
                    if (TryRedirectEntry(mod, i, $"{i}.raw"))
                    {
                        break;
                    }

                    if (waveBank.Entries[i].CueName != null)
                    {
                        // Try redirect from cue name
                        if (TryRedirectEntry(mod, i, waveBank.Entries[i].CueName + ".raw"))
                        {
                            break;
                        }
                    }
                }
            }
        }
예제 #3
0
        public long ReallocateFileData(int dataOffset, int length)
        {
            var offset             = mMapper.Reallocate(DataBaseOffset + dataOffset, length);
            var oldVirtualFileSize = VirtualFileSize;

            VirtualFileSize = Math.Max(VirtualFileSize, offset + length);
            if (VirtualFileSize > MAX_FILE_SIZE)
            {
                mLogger.Error("Out of available memory! 4GB address space exhausted");
            }
            else if (VirtualFileSize > oldVirtualFileSize)
            {
                mLogger.Info($"{FileName} Virtual size increased to 0x{VirtualFileSize:X8}");
            }

            return(( long )(offset - DataBaseOffset));
        }
        public bool TryRedirect(ModDb modDb)
        {
            RedirectAttempted = true;

            foreach (var mod in modDb.Mods)
            {
                var redirectedFilePath = Path.Combine(mod.LoadDirectory, Pack.FileName, Native->Path);
                if (mod.Files.Contains(redirectedFilePath))
                {
                    Redirect(redirectedFilePath);
                    mLogger.Info($"{Pack.FileName} {Native->Path} Redirected to {redirectedFilePath}");
                    return(true);
                }
                else
                {
                    mLogger.Debug($"No redirection for {Native->Path} because {redirectedFilePath} does not exist.");
                }
            }

            return(false);
        }
예제 #5
0
        private NtStatus ReadFile(IntPtr handle, IntPtr hEvent, IntPtr *apcRoutine, IntPtr *apcContext,
                                  ref Native.IO_STATUS_BLOCK ioStatus, byte *buffer, uint length, LARGE_INTEGER *byteOffset, IntPtr key,
                                  VirtualDwPack pack, long offset, long effOffset)
        {
            // File data read
            NtStatus result = NtStatus.Success;

            for (int i = 0; i < pack.Entries.Count; i++)
            {
                var entry      = pack.Entries[i];
                var dataOffset = (pack.Native.Data + entry.Native->DataOffset) - pack.Native.Ptr;
                if (effOffset < dataOffset || effOffset >= (dataOffset + entry.Native->CompressedSize))
                {
                    continue;
                }

                var fileDataOffset = effOffset - dataOffset;
                var readEndOffset  = fileDataOffset + length;
                if (readEndOffset > entry.Native->CompressedSize)
                {
                    continue;
                }

                // Make sure the file has been redirected
                // This is done as late as possible to improve startup times
                if (!entry.IsRedirected)
                {
                    mLogger.Info($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Data access Offset: 0x{effOffset:X8} Length: 0x{length:X8}");
                    result = mHooks.NtReadFileHook.OriginalFunction(handle, hEvent, apcRoutine, apcContext, ref ioStatus, buffer, length, byteOffset, key);
                }
                else
                {
                    mLogger.Info($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Data access Offset: 0x{effOffset:X8} Length: 0x{length:X8} redirected to {entry.RedirectedFilePath}");
                    result = NtStatus.Success;

                    if (fileDataOffset < 0)
                    {
                        mLogger.Error($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Offset is before start of data!!!");
                    }
                    else if (fileDataOffset > entry.RedirectedFileSize)
                    {
                        mLogger.Error($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Offset is after end of data!!!");
                    }

                    mLogger.Debug($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Reading 0x{length:X8} bytes from redirected file at offset 0x{fileDataOffset:X8}");

                    // Get cached file stream if the file was previously opened or open a new file
                    Stream redirectedStream;
                    if (mCachedFile == entry)
                    {
                        redirectedStream = mCachedFileStream;
                    }
                    else
                    {
                        mCachedFileStream?.Close();
                        mCachedFile       = entry;
                        mCachedFileStream = redirectedStream = entry.OpenRead();
                    }

                    // Read from redirected file into the buffer
                    try
                    {
                        redirectedStream.Seek(fileDataOffset, SeekOrigin.Begin);
                        var readBytes = redirectedStream.Read(new Span <byte>(( void * )buffer, ( int )length));
                        SetBytesRead(handle, ( int )offset, ( int )length, ref ioStatus);

                        if (readBytes != length)
                        {
                            mLogger.Error($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) File read length doesnt match requested read length!! Expected 0x{length:X8}, Actual 0x{readBytes:X8}");
                        }

                        mLogger.Debug($"{pack.FileName} Hnd: {handle} {entry.Native->Path} Idx: ({i}) Wrote redirected file to buffer");
                    }
                    catch (Exception e)
                    {
                        mLogger.Debug($"{pack.FileName} Hnd: {handle} Idx: {i} {entry.Native->Path} Unhandled exception thrown during reading {entry.RedirectedFilePath}: {e}");
                    }
                }

                // Return early, we're done here
                return(result);
            }

            mLogger.Error($"{pack.FileName} Hnd: {handle} Unhandled file data read request!! Offset: 0x{effOffset:X8} Length: 0x{length:X8}");
            return(mHooks.NtReadFileHook.OriginalFunction(handle, hEvent, apcRoutine, apcContext, ref ioStatus, buffer, length, byteOffset, key));
        }