public override unsafe NtStatus NtSetInformationFileImpl(IntPtr hfile, out IO_STATUS_BLOCK ioStatusBlock,
                                                                 void *fileInformation, uint length, FileInformationClass fileInformationClass)
        {
            if (fileInformationClass == FileInformationClass.FilePositionInformation)
            {
                var pack = mPacksByHandle[hfile];
                pack.FilePointer = *( long * )fileInformation;
                mLogger.Debug($"{pack.Instance.FileName} Hnd: {hfile} SetFilePointer -> 0x{pack.FilePointer:X8}");
            }
            else
            {
                mLogger.Warning($"SetInformationFileImpl(hfile = {hfile}, out ioStatusBlock, fileInformation = *0x{( long )fileInformation:X8}, " +
                                $"length = {length}, fileInformationClass = {fileInformationClass}");
            }

            mHooks.NtSetInformationFileHook.OriginalFunction(hfile, out ioStatusBlock, fileInformation, length, fileInformationClass);

            // Spoof return value as we extend beyond the end of the file
            return(NtStatus.Success);
        }
Exemple #2
0
        private bool ParseTxth(string path)
        {
            using (var reader = new StreamReader(path))
            {
                var txth = new ParsedTxth();

                while (!reader.EndOfStream)
                {
                    var line  = reader.ReadLine();
                    var kvp   = line.Split("=", StringSplitOptions.RemoveEmptyEntries);
                    var key   = kvp[0].Trim();
                    var value = kvp[1].Trim();
                    int temp  = 0;

                    switch (key)
                    {
                    case "num_samples":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.Duration = temp;
                        break;

                    case "codec":
                        switch (value)
                        {
                        case "PCM16LE":
                            txth.FormatTag = WaveBankMiniFormatTag.PCM;
                            txth.BitDepth  = WaveBankMiniFormatBitDepth._16;
                            break;

                        case "PCM8":
                            txth.FormatTag = WaveBankMiniFormatTag.PCM;
                            txth.BitDepth  = WaveBankMiniFormatBitDepth._8;
                            break;

                        case "XMA2":
                            txth.FormatTag = WaveBankMiniFormatTag.XMA;
                            break;

                        case "MSADPCM":
                            txth.FormatTag = WaveBankMiniFormatTag.ADPCM;
                            break;

                        case "XWMA":
                            txth.FormatTag = WaveBankMiniFormatTag.WMA;
                            break;

                        default:
                            mLogger.Error($"Unsupported codec ({value})");
                            return(false);
                        }
                        break;

                    case "channels":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.Channels = temp;
                        break;

                    case "sample_rate":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.SampleRate = temp;
                        break;

                    case "interleave":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.Interleave = temp;
                        break;

                    case "loop_start_sample":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.LoopStart = temp;
                        break;

                    case "loop_end_sample":
                        if (!int.TryParse(value, out temp))
                        {
                            return(false);
                        }
                        txth.LoopEnd = temp;
                        break;

                    default:
                        mLogger.Error($"{path} Unrecognized TXTH command: {key} = {value}");
                        break;
                    }
                }

                if (!txth.Duration.HasValue)
                {
                    mLogger.Error($"{path} num_samples is not set!");
                    return(false);
                }

                if (!txth.FormatTag.HasValue)
                {
                    mLogger.Error($"{path} codec is not set!");
                    return(false);
                }

                if (!txth.Channels.HasValue)
                {
                    mLogger.Error($"{path} channels is not set!");
                    return(false);
                }

                if (!txth.SampleRate.HasValue)
                {
                    mLogger.Error($"{path} sample_rate is not set!");
                    return(false);
                }

                if (!txth.Interleave.HasValue)
                {
                    mLogger.Error($"{path} interleave is not set!");
                    return(false);
                }

                if (txth.LoopStart.HasValue && !txth.LoopEnd.HasValue)
                {
                    // Set end loop sample to the duration if it is somehow missing
                    txth.LoopEnd = txth.Duration;
                }

                // Set settings
                Native->Format.FormatTag.Set(txth.FormatTag.Value);
                Native->Format.BitsPerSample.Set(txth.BitDepth.GetValueOrDefault(0));
                Native->Format.Channels.Set(txth.Channels.Value);
                Native->Format.SamplesPerSecond.Set(txth.SampleRate.Value);
                Native->Format.CalculatedBlockAlign = txth.Interleave.Value;

                var durationAligned = WaveBankFormatHelper.AlignSamples(Native->Format.FormatTag.Get(), txth.Duration.Value,
                                                                        Native->Format.CalculatedBlockAlign, Native->Format.Channels);

                if (txth.LoopStart.HasValue)
                {
                    var startSampleAligned = WaveBankFormatHelper.AlignSamples(Native->Format.FormatTag.Get(), txth.LoopStart.Value,
                                                                               Native->Format.CalculatedBlockAlign, Native->Format.Channels);
                    var startSampleAlignedDiff = startSampleAligned - txth.LoopStart.Value;
                    var endSampleAligned       = WaveBankFormatHelper.AlignSamples(Native->Format.FormatTag.Get(), txth.LoopEnd.Value + startSampleAlignedDiff,
                                                                                   Native->Format.CalculatedBlockAlign, Native->Format.Channels);
                    var endSampleAlignedOff = endSampleAligned - txth.LoopEnd.Value;

                    if (startSampleAlignedDiff > 0)
                    {
                        mLogger.Warning($"{path} Loop start sample is not aligned properly, it may not loop correctly ingame!");
                    }
                    if (endSampleAlignedOff > 0)
                    {
                        mLogger.Warning($"{path} Loop end sample is not aligned properly, it may not loop correctly ingame!");
                    }

                    Native->LoopRegion.StartSample  = startSampleAligned;
                    Native->LoopRegion.TotalSamples = endSampleAligned - startSampleAligned;

                    if (endSampleAligned > durationAligned)
                    {
                        durationAligned = endSampleAligned;
                    }
                }
                else
                {
                    Native->LoopRegion.StartSample  = 0;
                    Native->LoopRegion.TotalSamples = 0;
                }

                if (durationAligned > txth.Duration)
                {
                    mLogger.Warning($"[{path} Duration is not aligned properly, it may not play correctly ingame!");
                }

                Native->FlagsAndDuration.Duration.Set(( uint )durationAligned);
            }

            return(true);
        }