Example #1
0
 public Lump(aBinaryReader reader)
     : this()
 {
     Start  = reader.ReadS32();
     Length = reader.ReadS32();
     Name   = reader.ReadString <aCSTR>(8);
 }
Example #2
0
 public Lump(aBinaryReader reader)
     : this()
 {
     Start = reader.ReadS32();
     Length = reader.ReadS32();
     Name = reader.ReadString<aCSTR>(8);
 }
Example #3
0
        void LoadRiffBlock()
        {
            switch (mReader.ReadString(4))
            {
            case "RIFF": break;

            case "RIFX": mReader.Endianness = Endianness.Big; break;

            default: mareep.WriteError("WAV: could not find 'RIFF'."); break;
            }

            mSize = mReader.ReadS32();

            if (mReader.ReadString(4) != "WAVE")
            {
                mareep.WriteError("WAV: could not find 'WAVE'.");
            }

            var fmt  = false;
            var data = false;

            while ((mReader.Position - 8) < mSize)
            {
                var id    = mReader.ReadString(4);
                var size  = mReader.ReadS32();
                var start = mReader.Position;

                switch (id)
                {
                case "fmt ": fmt = true; LoadFmtBlock(size); break;

                case "data": data = true; LoadDataBlock(size); break;
                }

                mReader.Goto(start + size);
            }

            if (!fmt)
            {
                mareep.WriteError("WAV: missing 'fmt ' chunk.");
            }
            else if (!data)
            {
                mareep.WriteError("WAV: missing 'data' chunk.");
            }

            // calculate sample count here to ensure fmt has been loaded
            mSampleCount = (mDataSize / mBlockAlign);
        }
Example #4
0
        static bool ReadAafHeader(aBinaryReader reader, int id, int index, out int offset, out int size)
        {
            int section;

            offset = 0;
            size   = 0;

            while ((section = reader.ReadS32()) != 0)
            {
                if (section == 2 || section == 3)
                {
                    for (int i = 0; (offset = reader.ReadS32()) != 0; ++i)
                    {
                        size = reader.ReadS32();
                        reader.Step(4);

                        if (section == id && i == index)
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    offset = reader.ReadS32();
                    size   = reader.ReadS32();
                    reader.Step(4);

                    if (section == id && index == 0)
                    {
                        return(true);
                    }
                }

                if (section == id)
                {
                    break;
                }
            }

            return(false);
        }
Example #5
0
        public void load(aBinaryReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            reader.PushAnchor();
            var entryCount  = reader.ReadS32();
            var fieldCount  = reader.ReadS32();
            var entryOffset = reader.Read32();
            var entrySize   = reader.ReadS32();

            mFields = new jmpField[fieldCount];
            for (var i = 0; i < fieldCount; ++i)
            {
                mFields[i].hash    = reader.Read32();
                mFields[i].bitmask = reader.Read32();
                mFields[i].start   = reader.Read16();
                mFields[i].shift   = reader.Read8();
                mFields[i].type    = (jmpValueType)reader.Read8();
            }
            mEntries = new jmpValue[entryCount, fieldCount];
            for (var entry = 0; entry < entryCount; ++entry)
            {
                for (var field = 0; field < fieldCount; ++field)
                {
                    reader.Goto(entryOffset + (entrySize * entry) + mFields[field].start);
                    switch (mFields[field].type)
                    {
                    case jmpValueType.INTEGER: mEntries[entry, field] = (int)((reader.ReadS32() & mFields[field].bitmask) >> mFields[field].shift); break;

                    case jmpValueType.FLOAT: mEntries[entry, field] = reader.ReadF32(); break;

                    case jmpValueType.STRING: mEntries[entry, field] = reader.ReadString <aCSTR>(0x20); break;
                    }
                }
            }
            reader.PopAnchor();
        }
Example #6
0
        static bool ReadBarcHeader(aBinaryReader reader, string seq, int count, out int index, out int offset, out int size)
        {
            index = ConvertSeqNameToIndex(seq);
            long start = reader.Position;

            offset = 0;
            size   = 0;

            if (index > 0)
            {
                if (index >= count)
                {
                    return(false);
                }

                reader.Goto(start + 32 * index + 24);
                offset = reader.ReadS32();
                size   = reader.ReadS32();
                return(true);
            }

            for (int i = 0; i < count; ++i)
            {
                reader.Goto(start + 32 * i);
                string name = reader.ReadString <aZSTR>();

                if (name.Equals(seq, StringComparison.InvariantCultureIgnoreCase))
                {
                    reader.Goto(start + 32 * i + 24);
                    offset = reader.ReadS32();
                    size   = reader.ReadS32();
                    index  = i;
                    return(true);
                }
            }

            return(false);
        }
Example #7
0
        void PerformStreamToWav(Stream instream, Stream outstream)
        {
            var reader = new aBinaryReader(instream, Endianness.Big);
            var writer = new aBinaryWriter(outstream, Endianness.Little);

            var streamDataSize = reader.ReadS32();
            var sampleCount    = reader.ReadS32();
            var sampleRate     = reader.Read16();
            var dataSize       = (sampleCount * 4);
            var format         = (StreamFormat)reader.Read16();

            writer.WriteString("RIFF");
            writer.WriteS32(36 + dataSize);
            writer.WriteString("WAVE");
            writer.WriteString("fmt ");
            writer.WriteS32(16);
            writer.WriteS16(1);              // format
            writer.Write16(2);               // channel count
            writer.WriteS32(sampleRate);
            writer.WriteS32(sampleRate * 4); // byte rate
            writer.Write16(4);               // block align
            writer.Write16(16);              // bit depth
            writer.WriteString("data");
            writer.WriteS32(dataSize);

            reader.Goto(32);

            switch (format)
            {
            case StreamFormat.Pcm: DecodeStreamPcm(reader, writer, sampleCount); break;

            case StreamFormat.Adpcm: DecodeStreamAdpcm(reader, writer, sampleCount); break;

            default: mareep.WriteError("AFC: Unknown format '{0}' in header.", (int)format); break;
            }
        }
Example #8
0
        protected void LoadMidi(Stream stream)
        {
            mReader = new aBinaryReader(stream, Endianness.Big, Encoding.ASCII);
            mReader.PushAnchor();
            mTracks = new List <TrackChunkInfo>();

            var mthd   = false;
            var tracks = 0;

            while (!mReader.IsAtEndOfStream)
            {
                if (mReader.BytesRemaining < 8)
                {
                    mareep.WriteWarning("MIDI: incomplete chunk at file end.\n");
                    break;
                }

                var id    = mReader.ReadString(4);
                var size  = mReader.ReadS32();
                var start = mReader.Position;

                switch (id)
                {
                case "MThd": mthd = true; LoadMThd(size); break;

                case "MTrk": ++tracks; LoadMTrk(size); break;
                }

                mReader.Goto(start + size);
            }

            if (!mthd)
            {
                mareep.WriteError("MIDI: missing header chunk.");
            }

            if (tracks != mTrackCount)
            {
                mareep.WriteWarning("MIDI: track count mismatch (header says {0}, found {1}).\n", mTrackCount, tracks);
                mTrackCount = tracks;
            }

            if (mFormat == 0 && mTrackCount != 1)
            {
                mareep.WriteWarning("MIDI: format-0 requires a single track.");
            }
        }
Example #9
0
        void DoExtractWsys()
        {
            if (mAafInPath == null)
            {
                mareep.WriteError("CHARGE: missing -init-data-file parameter");
            }

            if (mOutput == null)
            {
                mareep.WriteError("CHARGE: missing -output parameter");
            }

            if (mTarget == null)
            {
                mareep.WriteError("CHARGE: missing -target parameter");
            }

            int index;

            if (!Int32.TryParse(mTarget, out index))
            {
                mareep.WriteError("CHARGE: bad target {0}", mTarget);
            }

            using (Stream stream = mareep.OpenFile(mAafInPath)) {
                mareep.WriteMessage("Scanning AAF header...\n");
                aBinaryReader reader = new aBinaryReader(stream, Endianness.Big);
                int           offset, size;

                if (!ReadAafHeader(reader, 3, index, out offset, out size))
                {
                    mareep.WriteError("CHARGE: failed to find wave bank data\n");
                }

                reader.Goto(offset);

                if (reader.ReadS32() != 0x57535953)                   // 'WSYS'
                {
                    mareep.WriteError("CHARGE: could not find 'WSYS' header");
                }

                mareep.WriteMessage("Found wave bank data {0} (0x{1:X6}, 0x{2:X6})\n", index, offset, size);
                mareep.WriteMessage("Extracting wave bank data...\n");
                reader.Goto(offset);
                WriteFileData(mOutput, reader.Read8s(size));
            }
        }
Example #10
0
            public GlyphBlock(aBinaryReader reader)
            {
                firstCode   = reader.Read16();                  // 0008
                lastCode    = reader.Read16();                  // 000A
                cellWidth   = reader.Read16();                  // 000C
                cellHeight  = reader.Read16();                  // 000E
                sheetSize   = reader.ReadS32();                 // 0010
                sheetFormat = (gxTextureFormat)reader.Read16(); // 0014
                sheetRow    = reader.Read16();                  // 0016
                sheetColumn = reader.Read16();                  // 0018
                sheetWidth  = reader.Read16();                  // 001A
                sheetHeight = reader.Read16();                  // 001C
                reader.Step(2);                                 // 001E

                // we have to manually calculate how many sheets there are
                int sheetCount = (((lastCode - firstCode) / (sheetRow * sheetColumn)) + 1);

                sheets = aCollection.Initialize(sheetCount, () => reader.Read8s(sheetSize));
            }
Example #11
0
        static void Main(string[] arguments)
        {
            Message("doomwadcorrupter v{0} arookas", new Version(0, 1, 12));
            Separator();
            if (arguments == null || arguments.Length < 2)
            {
                Message("Usage: doomwadcorrupter <input.wad> <output.wad> [options]");
                Message();
                Message("Options:");
                Message("    -start <value>");
                Message("    -end <value>");
                Message("    -inc <value>");
                Message("    -mode <type> [<value>]");
                Message("    -skip <filter> [<filter> [...]]");
                Message("    -only <filter> [<filter> [...]]");
                Message("    -zdoom");
                Message();
                Message("For more detailed instructions, refer to the official repo page.");
                Pause();
                Exit(false);
            }
            var inputWAD  = arguments[0];
            var outputWAD = arguments[1];

            cmd     = new aCommandLine(arguments.Skip(2).ToArray());
            options = new CorrupterOptions(cmd);
            DisplayOptions(inputWAD, outputWAD);

            int lumpCount;
            var lumpsCorrupted = 0;
            var lumpsSkipped   = 0;
            var bytesCorrupted = 0;

            rnd = new Random((uint)options.CorruptSeed);
            var timeTaken = Stopwatch.StartNew();

            using (var instream = OpenWAD(inputWAD)) {
                var reader = new aBinaryReader(instream, Endianness.Little, Encoding.ASCII);

                // header
                var wadType = reader.ReadString(4);

                if (wadType != "IWAD" && wadType != "PWAD")
                {
                    Error("Input file is not a DOOM WAD.");
                }

                lumpCount = reader.ReadS32();
                var directoryOffset = reader.ReadS32();

                // directory
                reader.Goto(directoryOffset);
                var lumps = aCollection.Initialize(lumpCount, () => new Lump(reader));

                using (var outstream = CreateWAD(outputWAD)) {
                    var writer = new aBinaryWriter(outstream, Endianness.Little, Encoding.ASCII);
                    // header
                    writer.WriteString(wadType);
                    writer.WriteS32(lumpCount);
                    writer.WriteS32(directoryOffset);

                    // data
                    var corruptBuff = new byte[options.Increment];
                    var startBuff   = new byte[options.Start];
                    var ns          = LumpNamespace.Global;

                    foreach (var lump in lumps)
                    {
                        reader.Goto(lump.Start);
                        writer.Goto(lump.Start);
                        CheckNamespaceMarker(lump, ref ns);
                        if (options.Filter.IsCorruptable(lump.Name, ns) && !(options.ZDOOM && IsZDOOMLump(lump.Name)))
                        {
                            ++lumpsCorrupted;
                            var i   = options.Start;
                            var end = options.End ?? lump.Length;
                            if (i > 0)
                            {
                                var count = (int)System.Math.Min(lump.Length, i);
                                reader.Read(startBuff, count);
                                writer.Write8s(startBuff, count);
                            }
                            while (i < lump.Length && i < end)
                            {
                                Status("Corrupting '{0}'... (0x{1:X8} / 0x{2:X8})", lump.Name, i, lump.Length);
                                var count = (int)System.Math.Min(lump.Length - i, options.Increment);
                                reader.Read(corruptBuff, count);
                                CorruptByte(ref corruptBuff[0], options.CorruptMode, options.CorruptValue);
                                writer.Write8s(corruptBuff, count);
                                ++bytesCorrupted;
                                i += count;
                            }
                        }
                        else
                        {
                            ++lumpsSkipped;
                            writer.Write8s(reader.Read8s(lump.Length));
                        }
                    }

                    // directory
                    writer.Goto(directoryOffset);
                    foreach (var lump in lumps)
                    {
                        Status("Writing lump directory for '{0}'...", lump.Name);
                        lump.ToStream(writer);
                    }
                }
            }

            timeTaken.Stop();
            Status("Finished corrupting.");
            Message();
            Separator();
            Message("                       Files : {0}", lumpCount);
            Message("             Files corrupted : {0}", lumpsCorrupted);
            Message("               Files skipped : {0}", lumpsSkipped);
            Message("Bytes mercilessly sacrificed : {0}", bytesCorrupted);
            Message("                  Time taken : {0}", timeTaken.Elapsed.ToString("g"));
            Message("                 Finished at : {0}", DateTime.Now.ToString("HH:mm:ss tt"));
            Pause();
        }
        static void Main(string[] arguments)
        {
            Message("doomwadcorrupter v{0} arookas", new Version(0, 1, 12));
            Separator();
            if (arguments == null || arguments.Length < 2) {
                Message("Usage: doomwadcorrupter <input.wad> <output.wad> [options]");
                Message();
                Message("Options:");
                Message("    -start <value>");
                Message("    -end <value>");
                Message("    -inc <value>");
                Message("    -mode <type> [<value>]");
                Message("    -skip <filter> [<filter> [...]]");
                Message("    -only <filter> [<filter> [...]]");
                Message("    -zdoom");
                Message();
                Message("For more detailed instructions, refer to the official repo page.");
                Pause();
                Exit(false);
            }
            var inputWAD = arguments[0];
            var outputWAD = arguments[1];
            cmd = new aCommandLine(arguments.Skip(2).ToArray());
            options = new CorrupterOptions(cmd);
            DisplayOptions(inputWAD, outputWAD);

            int lumpCount;
            var lumpsCorrupted = 0;
            var lumpsSkipped = 0;
            var bytesCorrupted = 0;
            rnd = new Random((uint)options.CorruptSeed);
            var timeTaken = Stopwatch.StartNew();
            using (var instream = OpenWAD(inputWAD)) {
                var reader = new aBinaryReader(instream, Endianness.Little, Encoding.ASCII);

                // header
                var wadType = reader.ReadString(4);

                if (wadType != "IWAD" && wadType != "PWAD") {
                    Error("Input file is not a DOOM WAD.");
                }

                lumpCount = reader.ReadS32();
                var directoryOffset = reader.ReadS32();

                // directory
                reader.Goto(directoryOffset);
                var lumps = aCollection.Initialize(lumpCount, () => new Lump(reader));

                using (var outstream = CreateWAD(outputWAD)) {
                    var writer = new aBinaryWriter(outstream, Endianness.Little, Encoding.ASCII);
                    // header
                    writer.WriteString(wadType);
                    writer.WriteS32(lumpCount);
                    writer.WriteS32(directoryOffset);

                    // data
                    var corruptBuff = new byte[options.Increment];
                    var startBuff = new byte[options.Start];
                    var ns = LumpNamespace.Global;

                    foreach (var lump in lumps) {
                        reader.Goto(lump.Start);
                        writer.Goto(lump.Start);
                        CheckNamespaceMarker(lump, ref ns);
                        if (options.Filter.IsCorruptable(lump.Name, ns) && !(options.ZDOOM && IsZDOOMLump(lump.Name))) {
                            ++lumpsCorrupted;
                            var i = options.Start;
                            var end = options.End ?? lump.Length;
                            if (i > 0) {
                                var count = (int)System.Math.Min(lump.Length, i);
                                reader.Read(startBuff, count);
                                writer.Write8s(startBuff, count);
                            }
                            while (i < lump.Length && i < end) {
                                Status("Corrupting '{0}'... (0x{1:X8} / 0x{2:X8})", lump.Name, i, lump.Length);
                                var count = (int)System.Math.Min(lump.Length - i, options.Increment);
                                reader.Read(corruptBuff, count);
                                CorruptByte(ref corruptBuff[0], options.CorruptMode, options.CorruptValue);
                                writer.Write8s(corruptBuff, count);
                                ++bytesCorrupted;
                                i += count;
                            }
                        }
                        else {
                            ++lumpsSkipped;
                            writer.Write8s(reader.Read8s(lump.Length));
                        }
                    }

                    // directory
                    writer.Goto(directoryOffset);
                    foreach (var lump in lumps) {
                        Status("Writing lump directory for '{0}'...", lump.Name);
                        lump.ToStream(writer);
                    }
                }
            }

            timeTaken.Stop();
            Status("Finished corrupting.");
            Message();
            Separator();
            Message("                       Files : {0}", lumpCount);
            Message("             Files corrupted : {0}", lumpsCorrupted);
            Message("               Files skipped : {0}", lumpsSkipped);
            Message("Bytes mercilessly sacrificed : {0}", bytesCorrupted);
            Message("                  Time taken : {0}", timeTaken.Elapsed.ToString("g"));
            Message("                 Finished at : {0}", DateTime.Now.ToString("HH:mm:ss tt"));
            Pause();
        }
Example #13
0
        void DoExtractSeq()
        {
            if (mAafInPath == null)
            {
                mareep.WriteError("CHARGE: missing -init-data-file parameter");
            }

            if (mArcInPath == null)
            {
                mareep.WriteError("CHARGE: missing -seq-data-file parameter");
            }

            if (mOutput == null)
            {
                mareep.WriteError("CHARGE: missing -output parameter");
            }

            if (mTarget == null)
            {
                mareep.WriteError("CHARGE: missing -target parameter");
            }

            int offset, size;

            using (Stream stream = mareep.OpenFile(mAafInPath)) {
                mareep.WriteMessage("Scanning AAF header...\n");
                aBinaryReader reader = new aBinaryReader(stream, Endianness.Big);

                if (!ReadAafHeader(reader, 4, 0, out offset, out size))
                {
                    mareep.WriteError("CHARGE: failed to find sequence info data");
                }

                reader.Goto(offset);

                if (reader.ReadS32() != 0x42415243)                   // 'BARC'
                {
                    mareep.WriteError("CHARGE: could not find 'BARC' header");
                }

                reader.Goto(offset + 12);
                int count = reader.ReadS32();
                reader.Goto(offset + 32);
                int index;

                mareep.WriteMessage("Found sequence info data (0x{0:X6}, 0x{1:X6}), {2} sequence(s)\n", offset, size, count);
                mareep.WriteMessage("Scanning sequence list...\n");

                if (!ReadBarcHeader(reader, mTarget, count, out index, out offset, out size))
                {
                    mareep.WriteError("CHARGE: could not find sequence {0}", mTarget);
                }

                mareep.WriteMessage("Found sequence {0} (0x{1:X6}, 0x{2:X6})\n", index, offset, size);
            }

            mareep.WriteMessage("Extracting sequence data...\n");

            using (Stream stream = mareep.OpenFile(mArcInPath)) {
                aBinaryReader reader = new aBinaryReader(stream);
                reader.Goto(offset);
                WriteFileData(mOutput, reader.Read8s(size));
            }
        }
Example #14
0
        static bool WriteAafHeader(aBinaryReader reader, aBinaryWriter writer, int id, int index, byte[] data)
        {
            long reader_base = reader.Position;
            long writer_base = writer.Position;
            int  old_offset, old_size;

            if (!ReadAafHeader(reader, id, index, out old_offset, out old_size))
            {
                return(false);
            }

            int difference = (data.Length - old_size);

            reader.Goto(reader_base);
            int section;

            while ((section = reader.ReadS32()) != 0)
            {
                bool has_vnum = (section == 2 || section == 3);
                writer.WriteS32(section);
                int offset, size;
                int i = 0;

                while ((offset = reader.ReadS32()) != 0)
                {
                    size = reader.ReadS32();

                    if (offset > old_offset)
                    {
                        offset += difference;
                    }

                    writer.Keep();
                    writer.Goto(writer_base + offset);

                    if (section == id && i == index)
                    {
                        writer.Write8s(data);
                        size = data.Length;
                    }
                    else
                    {
                        reader.Keep();
                        reader.Goto(reader_base + offset);
                        writer.Write8s(reader.Read8s(size));
                        reader.Back();
                    }

                    writer.Back();
                    writer.WriteS32(offset);
                    writer.WriteS32(size);

                    if (has_vnum)
                    {
                        writer.WriteS32(reader.ReadS32());
                    }

                    ++i;
                }

                writer.WriteS32(0);
            }

            writer.WriteS32(0);
            writer.Goto(writer.Length);
            writer.WritePadding(32, 0);
            return(true);
        }
Example #15
0
        void DoReplaceSeq()
        {
            if (mAafInPath == null)
            {
                mareep.WriteError("CHARGE: missing -init-data-file parameter");
            }

            if (mArcInPath == null)
            {
                mareep.WriteError("CHARGE: missing -seq-data-file parameter");
            }

            byte[] arc_data = ReadFileData(mArcInPath);

            if (mInput == null)
            {
                mareep.WriteError("CHARGE: missing -input parameter");
            }

            byte[] seq_data = ReadFileData(mInput);

            if (mTarget == null)
            {
                mareep.WriteError("CHARGE: missing -target parameter");
            }

            byte[] barc_data = null;

            using (Stream input = mareep.OpenFile(mAafInPath)) {
                mareep.WriteMessage("Scanning AAF header...\n");
                aBinaryReader reader = new aBinaryReader(input, Endianness.Big);
                int           offset, size;

                if (!ReadAafHeader(reader, 4, 0, out offset, out size))
                {
                    mareep.WriteError("CHARGE: failed to find sequence info block");
                }

                reader.Goto(offset);

                if (reader.ReadS32() != 0x42415243)                   // 'BARC'
                {
                    mareep.WriteError("CHARGE: could not find 'BARC' header");
                }

                reader.Goto(offset + 12);
                int count = reader.ReadS32();
                barc_data = new byte[32 + 32 * count];
                reader.Goto(offset + 32);
                int index, old_offset, old_size;

                mareep.WriteMessage("Found sequence info data (0x{0:X6}, 0x{1:X6}), {2} sequence(s)\n", offset, size, count);
                mareep.WriteMessage("Scanning sequence list...\n");

                if (!ReadBarcHeader(reader, mTarget, count, out index, out old_offset, out old_size))
                {
                    mareep.WriteError("CHARGE: could not find sequence {0}", mTarget);
                }

                mareep.WriteMessage("Found sequence {0} (0x{1:X6}, 0x{2:X6})\n", index, offset, size);

                int new_offset, new_size = ((seq_data.Length + 31) & ~31);
                int difference = (new_size - old_size);
                reader.Goto(offset + 16);

                using (Stream arc_stream = mareep.CreateFile(mArcOutPath))
                    using (MemoryStream barc_stream = new MemoryStream(barc_data, true)) {
                        mareep.WriteMessage("Writing new sequence data...\n");
                        aBinaryWriter arc_writer  = new aBinaryWriter(arc_stream);
                        aBinaryWriter barc_writer = new aBinaryWriter(barc_stream, Endianness.Big);
                        barc_writer.WriteS32(0x42415243);                 // 'BARC'
                        barc_writer.WriteS32(0x2D2D2D2D);                 // '----'
                        barc_writer.WriteS32(0);
                        barc_writer.WriteS32(count);
                        barc_writer.Write8s(reader.Read8s(16));

                        for (int i = 0; i < count; ++i)
                        {
                            barc_writer.Write8s(reader.Read8s(14));
                            barc_writer.WriteS16(reader.ReadS16());
                            barc_writer.WriteS32(reader.ReadS32());
                            barc_writer.WriteS32(reader.ReadS32());
                            offset     = reader.ReadS32();
                            size       = reader.ReadS32();
                            new_offset = offset;

                            if (offset > old_offset)
                            {
                                new_offset += difference;
                            }

                            arc_writer.Goto(new_offset);

                            if (i == index)
                            {
                                arc_writer.Write8s(seq_data);
                                arc_writer.WritePadding(32, 0);
                                size = new_size;
                            }
                            else
                            {
                                arc_writer.Write8s(arc_data, offset, size);
                            }

                            barc_writer.WriteS32(new_offset);
                            barc_writer.WriteS32(size);
                        }
                    }

                reader.Goto(0);

                using (Stream output = mareep.CreateFile(mAafOutPath)) {
                    mareep.WriteMessage("Writing new AAF file...\n");
                    aBinaryWriter writer = new aBinaryWriter(output, Endianness.Big);

                    if (!WriteAafHeader(reader, writer, 4, 0, barc_data))
                    {
                        mareep.WriteError("CHARGE: failed to write aaf file");
                    }
                }
            }
        }
Example #16
0
        protected override WaveBank DoTransform(WaveBank obj)
        {
            if (obj != null)
            {
                return(obj);
            }

            mReader.Keep();
            mReader.PushAnchor();

            if (mReader.Read32() != WSYS)
            {
                mareep.WriteError("WSYS: could not find header.");
            }

            var size = mReader.ReadS32();

            mReader.Step(8);             // unused
            var winfOffset = mReader.ReadS32();
            var wbctOffset = mReader.ReadS32();

            mareep.WriteMessage("WSYS: header found, size {0:F1} KB\n", ((double)size / 1024.0d));

            var waveBank = new WaveBank();

            waveBank.Name = mName;

            mReader.Goto(winfOffset);

            if (mReader.Read32() != WINF)
            {
                mareep.WriteError("WSYS: could not find WINF at 0x{0:X6}.", winfOffset);
            }

            var waveGroupCount = mReader.ReadS32();

            if (waveGroupCount < 0)
            {
                mareep.WriteError("WSYS: bad wave-group count '{0}' in WINF.", waveGroupCount);
            }

            mareep.WriteMessage("WSYS: WINF found, {0} wave group(s).\n", waveGroupCount);

            var waveGroupOffsets = mReader.ReadS32s(waveGroupCount);

            mReader.Goto(wbctOffset);

            if (mReader.Read32() != WBCT)
            {
                mareep.WriteError("WSYS: could not find WBCT at 0x{0:X6}.", wbctOffset);
            }

            mReader.Step(4);             // unused

            var sceneCount = mReader.ReadS32();

            if (sceneCount != waveGroupCount)
            {
                mareep.WriteError("WSYS: WINF count ({0}) does not match WBCT count ({1}).", waveGroupCount, sceneCount);
            }

            var sceneOffsets = mReader.ReadS32s(sceneCount);

            for (var i = 0; i < waveGroupCount; ++i)
            {
                mReader.Goto(waveGroupOffsets[i]);

                var archiveName   = mReader.ReadString <aCSTR>(112);
                var waveInfoCount = mReader.ReadS32();

                if (waveInfoCount < 0)
                {
                    mareep.WriteError("WSYS: bad wave count '{0}' in wave group #{1}.", waveInfoCount, i);
                }

                var waveInfoOffsets = mReader.ReadS32s(waveInfoCount);

                mReader.Goto(sceneOffsets[i]);

                if (mReader.Read32() != SCNE)
                {
                    mareep.WriteError("WSYS: could not find SCNE at 0x{0:X6}.", sceneOffsets[i]);
                }

                mReader.Step(8);                 // unused
                var cdfOffset = mReader.ReadS32();
                mReader.Goto(cdfOffset);

                if (mReader.Read32() != C_DF)
                {
                    mareep.WriteError("WSYS: could not find C-DF at 0x{0:X6}.", cdfOffset);
                }

                var waveidCount = mReader.ReadS32();

                if (waveidCount != waveInfoCount)
                {
                    mareep.WriteError("WSYS: C-DF count ({0}) does not match wave-info count ({1}).", waveidCount, waveInfoCount);
                }

                var waveidOffsets = mReader.ReadS32s(waveidCount);

                var waveGroup = new WaveGroup();
                waveGroup.ArchiveFileName = archiveName;

                for (var j = 0; j < waveInfoCount; ++j)
                {
                    var wave = new Wave();

                    mReader.Goto(waveidOffsets[j]);

                    var waveid = (mReader.ReadS32() & 0xFFFF);
                    wave.WaveId = waveid;

                    mReader.Goto(waveInfoOffsets[j]);
                    mReader.Step(1);                     // unknown

                    var format = (WaveFormat)mReader.Read8();

                    if (!format.IsDefined())
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad format '{2}'.", i, j, (byte)format);
                    }
                    else
                    {
                        wave.Format = format;
                    }

                    var key = mReader.Read8();

                    if (key < 0 || key > 127)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad root key '{2}'.", i, j, key);
                    }
                    else
                    {
                        wave.RootKey = key;
                    }

                    mReader.Step(1);                     // alignment

                    var sampleRate = mReader.ReadF32();

                    if (sampleRate < 0.0f)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad sample rate '{2:F1}'.", i, j, sampleRate);
                    }
                    else
                    {
                        wave.SampleRate = sampleRate;
                    }

                    var waveStart = mReader.ReadS32();

                    if (waveStart < 0)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad wave start '{2}'.", i, j, waveStart);
                    }
                    else
                    {
                        wave.WaveStart = waveStart;
                    }

                    var waveSize = mReader.ReadS32();

                    if (waveSize < 0)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad wave size '{1}'.", i, j, waveSize);
                    }
                    else
                    {
                        wave.WaveSize = waveSize;
                    }

                    wave.Loop = (mReader.Read32() != 0);

                    var loopStart = mReader.ReadS32();

                    if (loopStart < 0)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad loop start '{2}'.", i, j, loopStart);
                    }
                    else
                    {
                        wave.LoopStart = loopStart;
                    }

                    var loopEnd = mReader.ReadS32();

                    if (loopEnd < 0)
                    {
                        mareep.WriteError("WSYS: group #{0}: wave #{1}: bad loop end '{2}'.", i, j, loopEnd);
                    }
                    else
                    {
                        wave.LoopEnd = loopEnd;
                    }

                    var sampleCount = mReader.ReadS32();
                    wave.SampleCount = mareep.CalculateSampleCount(format, waveSize);

                    if (loopStart > loopEnd)
                    {
                        mareep.WriteWarning("WSYS: group #{0}: wave #{1}: loop start '{2}' is greater than loop end '{3}'.\n", i, j, loopStart, loopEnd);
                    }

                    if (loopStart > wave.SampleCount)
                    {
                        mareep.WriteWarning("WSYS: group #{0}: wave #{1}: loop start '{2}' is greater than sample count '{3}'.\n", i, j, loopStart, wave.SampleCount);
                    }

                    if (loopEnd > wave.SampleCount)
                    {
                        mareep.WriteWarning("WSYS: group #{0}: wave #{1}: loop end '{2}' is greater than sample count '{3}'.\n", i, j, loopEnd, wave.SampleCount);
                    }

                    wave.HistoryLast   = mReader.ReadS16();
                    wave.HistoryPenult = mReader.ReadS16();

                    // rest of the fields are unknown or runtime

                    waveGroup.Add(wave);
                }

                waveBank.Add(waveGroup);
            }

            mReader.PopAnchor();
            mReader.Back();

            return(waveBank);
        }
Example #17
0
 static void ReadHeader()
 {
     Console.WriteLine("Reading header...");
     if (sReader.Read32() != 0x53504342u)               // 'SPCB'
     {
         throw new Exception("Invalid magic.");
     }
     sTextOffset = sReader.Read32();
     sDataOffset = sReader.Read32();
     sDataCount  = sReader.ReadS32();
     sSymOffset  = sReader.Read32();
     sSymCount   = sReader.ReadS32();
     sVarCount   = sReader.ReadS32();
 }
Example #18
0
        static bool WriteAafHeader(aBinaryReader reader, aBinaryWriter writer, int id, int index, byte[] data)
        {
            long reader_base = reader.Position;
            long writer_base = writer.Position;
            int  old_offset, old_size;

            if (!ReadAafHeader(reader, id, index, out old_offset, out old_size))
            {
                return(false);
            }

            int difference = (data.Length - old_size);

            mareep.WriteMessage("Entry size difference: {0} byte(s)\n", difference);
            int danger_level = 0;

            reader.Goto(reader_base);
            int section;

            while ((section = reader.ReadS32()) != 0)
            {
                if (danger_level++ > 1000)
                {
                    mareep.WriteError("CHARGE: malformed AAF file (endless loop detected)");
                }

                bool has_vnum = (section == 2 || section == 3);
                writer.WriteS32(section);
                int offset, size;
                int i = 0;

                while ((offset = reader.ReadS32()) != 0)
                {
                    if (danger_level++ > 1000)
                    {
                        mareep.WriteError("CHARGE: malformed AAF file (endless loop detected)");
                    }

                    size = reader.ReadS32();
                    int new_offset = offset;

                    if (new_offset > old_offset)
                    {
                        new_offset += difference;
                    }

                    writer.Keep();
                    writer.Goto(writer_base + new_offset);

                    if (section == id && i == index)
                    {
                        writer.Write8s(data);
                        size = data.Length;
                    }
                    else
                    {
                        reader.Keep();
                        reader.Goto(reader_base + offset);
                        writer.Write8s(reader.Read8s(size));
                        reader.Back();
                    }

                    writer.Back();
                    writer.WriteS32(new_offset);
                    writer.WriteS32(size);

                    if (has_vnum)
                    {
                        writer.WriteS32(reader.ReadS32());
                    }

                    ++i;
                }

                writer.WriteS32(0);
            }

            writer.WriteS32(0);
            writer.Goto(writer.Length);
            writer.WritePadding(32, 0);
            return(true);
        }