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); }
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; } } } } }
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); }
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)); }