Beispiel #1
0
        protected void WriteSection(BinaryWriter writer, Stream stream)
        {
            // write length
            writer.Write((uint)stream.Length);

            // copy the stream to the underlying stream of the writer
            stream.CopyTo(writer.BaseStream);

            // write padding
            writer.AlignPosition(16);
        }
Beispiel #2
0
        // Methods
        internal void InternalWrite(BinaryWriter writer)
        {
            int size = GetSize();
            writer.Write(size);
            writer.Write(_numAssignedFrames);
            writer.Write(_type);

            for (int i = 0; i < _numAssignedFrames; i++)
            {
                writer.Write(_assignedFrameIndices[i]);
            }

            writer.AlignPosition(4);

            for (int i = 0; i < _numAssignedFrames; i++)
            {
                switch (_type)
                {
                    case 0x04:
                        {
                            for (int j = 0; j < 2; j++)
                            {
                                writer.Write((ushort)(_boneKeyData[i][j] * FIXED_POINT));
                            }
                        }

                        break;
                    case 0x08:
                        {
                            for (int j = 0; j < 4; j++)
                            {
                                writer.Write((ushort)(_boneKeyData[i][j] * FIXED_POINT));
                            }
                        }

                        break;
                    case 0x0C:
                        {
                            for (int j = 0; j < 3; j++)
                            {
                                writer.Write(_boneKeyData[i][j]);
                            }
                        }

                        break;
                    default:
                        break;
                }
            }
        }
        internal void InternalWrite(BinaryWriter writer)
        {
            writer.WriteStructure(_header);

            for (int i = 0; i < _header.entryCount; i++)
            {
                _subEntries[i].InternalWrite(writer);
            }

            writer.AlignPosition(16);

            for (int i = 0; i < _header.entryCount; i++)
            {
                if (i > 1 && _subEntries[i].Flags.HasFlagUnchecked(RecordFlags.DirectoryRecord))
                {
                    _subEntries[i].DirectoryListing.InternalWrite(writer);
                }
            }
        }
Beispiel #4
0
        // Internal Methods
        internal override void InternalWrite(BinaryWriter writer)
        {
            int posFileStart = (int)writer.BaseStream.Position;

            // Seek past chunk header
            writer.BaseStream.Seek(HEADER_SIZE + 4, SeekOrigin.Current);

            // Seek past texture pack header
            writer.BaseStream.Seek(TextureCount * sizeof(int), SeekOrigin.Current);

            int[] texturePointerTable = new int[TextureCount];

            // Write texture data
            for (int i = 0; i < TextureCount; i++)
            {
                writer.AlignPosition(64);
                texturePointerTable[i] = (int)(writer.BaseStream.Position - posFileStart);
                _textures[i].InternalWrite(writer);
            }

            // Calculate length
            long posFileEnd = writer.BaseStream.Position;
            int length = (int)(posFileEnd - posFileStart);

            // Write header
            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);
            writer.Write(FLAG);
            writer.Write((short)0); // userID
            writer.Write(length);
            writer.WriteCString(TAG, 4);
            writer.Write(0);
            writer.Write(TextureCount);

            // Write pointer table
            writer.Write(texturePointerTable);
            
            // Seek to end
            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
        }
Beispiel #5
0
        internal override void InternalWrite(BinaryWriter writer)
        {
            // Save the position of the file in the stream
            long posFileStart = writer.GetPosition();

            // Precalculate the first offset
            long posPrevDataEnd = (Entries.Count + 1) * BVPEntry.SIZE;

            // Write the entry table
            for (int i = 0; i < Entries.Count; i++)
            {
                // The offset is the position where the last data write ended, aligned to the 16 byte boundary
                Entries[i].FileDataOffset = (int)AlignmentHelper.Align(posPrevDataEnd, 16);

                // Write table entry
                Entries[i].WriteEntryHeader(writer);

                // Write data at offset
                writer.Write(Entries[i].Data, posFileStart + Entries[i].FileDataOffset);

                // Update the previous data end position
                posPrevDataEnd = Entries[i].FileDataOffset + Entries[i].DataLength;
            }

            // Write empty terminator entry
            writer.Write(0, BVPEntry.SIZE);

            // Seek to the last data write position, and align the file to 64 bytes
            writer.BaseStream.Seek(posPrevDataEnd, SeekOrigin.Begin);
            writer.AlignPosition(64);
        }
Beispiel #6
0
 /// <summary>
 /// Inherited from <see cref="RWNode"/>. Writes the data beyond the header.
 /// </summary>
 /// <param name="writer">The <see cref="BinaryWriter"/> to write the data with.</param>
 protected internal override void InternalWriteInnerData(BinaryWriter writer)
 {
     writer.WriteCString(Value);
     writer.AlignPosition(4);
 }
Beispiel #7
0
        internal override void InternalWrite(BinaryWriter writer)
        {
            // Save the start position to calculate the filesize and 
            // to write out the header after we know where all the structure offsets are
            Stream stream = writer.BaseStream;
            int posFileStart = (int)stream.Position;
            stream.Seek(SPR4Header.SIZE, SeekOrigin.Current);

            // Create initial header and tables
            SPR4Header header = new SPR4Header(TextureCount, KeyFrameCount);
            TypePointerTable[] keyFramePointerTable = new TypePointerTable[header.numKeyFrames];
            TypePointerTable[] texturePointerTable = new TypePointerTable[header.numTextures];

            // Set the pointer table offsets and seek past the entries
            // as the entries will be written later
            header.texturePointerTableOffset = (int)(stream.Position - posFileStart);
            stream.Seek(TypePointerTable.SIZE * header.numTextures, SeekOrigin.Current);

            header.keyFramePointerTableOffset = (int)(stream.Position - posFileStart);
            stream.Seek(TypePointerTable.SIZE * header.numKeyFrames, SeekOrigin.Current);

            // Write out the keyframe data and fill up the pointer table
            for (int i = 0; i < header.numKeyFrames; i++)
            {
                writer.AlignPosition(16);
                keyFramePointerTable[i].offset = (int)(stream.Position - posFileStart);
                _keyFrames[i].InternalWrite(writer);
            }

            writer.Seek(16, SeekOrigin.Current);
            writer.AlignPosition(16);

            // Write out the texture data and fill up the pointer table
            for (int i = 0; i < header.numTextures; i++)
            {
                texturePointerTable[i].offset = (int)(stream.Position - posFileStart);
                _textures[i].InternalWrite(writer);
                writer.Seek(16, SeekOrigin.Current);
            }

            // Save the end position
            long posFileEnd = stream.Position;

            // Seek back to the tables and write out the tables
            stream.Seek(posFileStart + header.texturePointerTableOffset, SeekOrigin.Begin);
            stream.WriteStructures(texturePointerTable, header.numTextures);

            stream.Seek(posFileStart + header.keyFramePointerTableOffset, SeekOrigin.Begin);
            stream.WriteStructures(keyFramePointerTable, header.numKeyFrames);

            // Seek back to the file and write out the header with
            // the offsets to the structures in the file
            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);
            writer.BaseStream.WriteStructure(header);

            // Set the file pointer back to the end of the file as expected
            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
        }
Beispiel #8
0
        internal override void InternalWrite(BinaryWriter writer)
        {
            int posFileStart = (int)writer.BaseStream.Position;

            // seek past the header, type table and code labels
            writer.BaseStream.Seek(DATA_START + (_procedures.Length * BFCodeLabel.SIZE) + (_jumpLabels.Length * BFCodeLabel.SIZE), SeekOrigin.Current);

            // create code label type table entries
            int procsLength = _procedures.Length * BFCodeLabel.SIZE;
            int jumpsLength = _jumpLabels.Length * BFCodeLabel.SIZE;

            int opCodeDataStart = (int)(writer.BaseStream.Position - posFileStart);
            int numProcsSet = 0;
            int numJumpsSet = 0;
            for (int i = 0; i < _opcodes.Count; i++)
            {
                int procIdx = -1;

                // try to find a procedure with this index
                if (numProcsSet != _procedures.Length)
                {
                    procIdx = Array.FindIndex(_procedures, p => p.OpcodeIndex == i);
                    if (procIdx != -1)
                    {
                        _procedures[procIdx].Offset = (uint)(((writer.BaseStream.Position - posFileStart) - opCodeDataStart) / 4);
                        numProcsSet++;
                    }
                }

                // if we haven't found a procedure, try to find a jump label with this index
                if (procIdx == -1 && numJumpsSet != _jumpLabels.Length)
                {
                    int jumpIdx = Array.FindIndex(_jumpLabels, j => j.OpcodeIndex == i);
                    if (jumpIdx != -1)
                    {
                        _jumpLabels[jumpIdx].Offset = (uint)(((writer.BaseStream.Position - posFileStart) - opCodeDataStart) / 4);
                        numJumpsSet++;
                    }
                }
                
                // write the opcode data
                writer.Write((ushort)_opcodes[i].Instruction);

                if (_opcodes[i].Operand != null)
                {
                    switch (_opcodes[i].Operand.Type)
                    {
                        case BFOperandType.Immediate:
                            if (_opcodes[i].Instruction == BFInstruction.PushUInt32)
                            {
                                writer.Write((ushort)0);
                                writer.Write((uint)_opcodes[i].Operand.ImmediateValue);
                            }
                            else
                            {
                                writer.Write((ushort)_opcodes[i].Operand.ImmediateValue);
                            }
                            break;
                        case BFOperandType.FloatingPoint:
                            writer.Write((ushort)0);
                            writer.Write((float)_opcodes[i].Operand.FloatValue);
                            break;
                    }
                }
                else
                {
                    writer.Write((ushort)0);
                }
            }

            int opCodeDataEnd = (int)(writer.BaseStream.Position - posFileStart);

            // set type table entries
            TypeTableEntry[] typeTableEntries = new TypeTableEntry[TYPE_TABLE_COUNT];
            typeTableEntries[(int)TypeTableType.Procedures] = CreateTypeTableEntry(TypeTableType.Procedures, procsLength, DATA_START);
            typeTableEntries[(int)TypeTableType.JumpLabels] = CreateTypeTableEntry(TypeTableType.JumpLabels, jumpsLength, DATA_START + procsLength);
            typeTableEntries[(int)TypeTableType.Opcodes]    = CreateTypeTableEntry(TypeTableType.Opcodes, opCodeDataEnd - opCodeDataStart, opCodeDataStart);
            typeTableEntries[(int)TypeTableType.Messages]   = CreateTypeTableEntry(TypeTableType.Messages, 0, opCodeDataEnd);
            typeTableEntries[(int)TypeTableType.Strings]    = CreateTypeTableEntry(TypeTableType.Strings, 0xF0, opCodeDataEnd);

            if (_messageFile != null)
            {
                _messageFile.InternalWrite(writer);
                int messageDataEnd = (int)writer.BaseStream.Position - posFileStart;
                int messageDataSize = messageDataEnd - opCodeDataEnd;

                typeTableEntries[(int)TypeTableType.Strings].dataOffset += messageDataSize;
                typeTableEntries[(int)TypeTableType.Messages] = CreateTypeTableEntry(TypeTableType.Messages, messageDataSize, opCodeDataEnd);
            }

            // TODO: add code for the 'string' table here? haven't really seen it being used though.
            // fixed size zero bytes for the strings table when unused
            writer.Write(0, 0xF0);

            long posFileEnd = writer.BaseStream.Position;
            int length = (int)posFileEnd - posFileStart;

            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);

            // write standard header
            writer.Write(TYPE);
            writer.Write((short)0); // userID
            writer.Write(length);
            writer.WriteCString(TAG, 4);
            writer.Write(0); // unused

            // write bf header
            writer.Write(typeTableEntries.Length);
            writer.Write(0); // some unknown value here, not sure what its for
            writer.AlignPosition(16);

            // write type table entries
            foreach (TypeTableEntry entry in typeTableEntries)
            {
                entry.InternalWrite(writer);
            }

            // lastly, write the code labels
            foreach (BFCodeLabel label in _procedures)
            {
                label.InternalWrite(writer);
            }

            foreach (BFCodeLabel label in _jumpLabels)
            {
                label.InternalWrite(writer);
            }
        }
Beispiel #9
0
        internal override void InternalWrite(BinaryWriter writer)
        {
            int posFileStart = (int)writer.BaseStream.Position;
            List<int> addressList = new List<int>();

            // Seek past chunk and msg header for writing later
            writer.BaseStream.Seek(DATA_START_ADDRESS, SeekOrigin.Current);

            // Write a dummy message pointer table
            for (int i = 0; i < DialogCount; i++)
            {
                writer.Write(0);
                addressList.Add((int)writer.BaseStream.Position - posFileStart);
                writer.Write(0);
            }

            // Write a dummy offset for writing later
            addressList.Add((int)writer.BaseStream.Position - posFileStart);
            writer.Write(0);
            writer.Write(ActorCount);

            // These are always here for some reason
            writer.Write(0);
            writer.Write(0);

            writer.AlignPosition(4);

            BMDMessageTable[] messagePointerTable = new BMDMessageTable[DialogCount];

            // Write the messages and fill in the message pointer table
            for (int i = 0; i < DialogCount; i++)
            {
                writer.AlignPosition(4);
                messagePointerTable[i].Offset = (int)writer.BaseStream.Position - DATA_START_ADDRESS - posFileStart;
                _messages[i].InternalWrite(writer, ref addressList, posFileStart);
            }

            writer.AlignPosition(4);
            int actorNamePointerTableOffset = (int)writer.BaseStream.Position - DATA_START_ADDRESS - posFileStart;

            // Write dummy actor name pointer table if there are actors present
            if (ActorCount > 0)
            {
                long actorNamePointerTablePosition = writer.BaseStream.Position;
                for (int i = 0; i < ActorCount; i++)
                {
                    addressList.Add((int)writer.BaseStream.Position - posFileStart);
                    writer.Write(0);
                }

                int[] actorNamePointerTable = new int[ActorCount];
                for (int i = 0; i < actorNamePointerTable.Length; i++)
                {
                    actorNamePointerTable[i] = (int)writer.BaseStream.Position - DATA_START_ADDRESS - posFileStart;
                    writer.WriteCString(_actorNames[i]);
                }

                long addresRelocPosition = writer.BaseStream.Position;

                writer.BaseStream.Seek(actorNamePointerTablePosition, SeekOrigin.Begin);
                writer.Write(actorNamePointerTable);

                writer.BaseStream.Seek(addresRelocPosition, SeekOrigin.Begin);
            }

            // Compress and write the address relocationt able
            byte[] addressRelocTable = PointerRelocationTableCompression.Compress(addressList, DATA_START_ADDRESS);
            int addressRelocTableOffset = (int)writer.BaseStream.Position - posFileStart;
            int addressRelocTableSize = addressRelocTable.Length;
            writer.Write(addressRelocTable);

            // Save the end offset for calculating length and seeking later
            long posFileEnd = writer.BaseStream.Position;
            int length = (int)(posFileEnd - posFileStart);

            // Seek back to the start
            writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin);

            // Write Chunk header
            writer.Write(FLAG);
            writer.Write((short)0); // userID
            writer.Write(length);
            writer.WriteCString(TAG, 4);
            writer.Write(0);

            // Write MSG header
            writer.Write(addressRelocTableOffset);
            writer.Write(addressRelocTableSize);
            writer.Write(DialogCount);
            writer.Write(UNK_CONSTANT);

            for (int i = 0; i < DialogCount; i++)
            {
                writer.Write((int)messagePointerTable[i].Type);
                writer.Write(messagePointerTable[i].Offset);
            }

            writer.Write(actorNamePointerTableOffset);

            writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin);
        }
        /*****************/
        /**** Methods ****/
        /*****************/

        internal void InternalWrite(BinaryWriter writer)
        {
            writer.WriteCString(_name, MAX_NAME_LENGTH);
            writer.Write(DataLength);
            writer.Write(Data);
            writer.AlignPosition(64);
        }