Пример #1
0
        internal static BMDMessage GetMessage(BinaryReader reader, int filePointer, BMDMessageTable msgTbl)
        {
            reader.BaseStream.Seek(filePointer + BMDFile.DATA_START_ADDRESS + msgTbl.Offset, SeekOrigin.Begin);
            switch (msgTbl.Type)
            {
                case BMDMessageType.Standard:
                    return new BMDStandardMessage(reader, filePointer);

                case BMDMessageType.Selection:
                    return new BMDSelectionMessage(reader, filePointer);

                default:
                    throw new ArgumentException("Unknown message type: " + msgTbl.Type);
            }
        }
Пример #2
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);
        }
Пример #3
0
        private void InternalRead(BinaryReader reader)
        {
            long posFileStart = reader.GetPosition();
            short flag = reader.ReadInt16();
            short userID = reader.ReadInt16();
            int length = reader.ReadInt32();
            string tag = reader.ReadCString(4);
            reader.AlignPosition(16);

            if (tag != TAG)
            {
                throw new InvalidDataException();
            }

            int addressRelocTableOffset = reader.ReadInt32();
            int addressRelocTableSize = reader.ReadInt32();
            int numMessages = reader.ReadInt32();
            short isRelocated = reader.ReadInt16(); // actually a byte but not very important
            short unk0x1E = reader.ReadInt16();

            /*
            if (unk0x1C != UNK_CONSTANT)
            {
                Console.WriteLine("_unk0x1C isn't 0x20000");
            }
            */

            BMDMessageTable[] messagePointerTable = new BMDMessageTable[numMessages];
            for (int i = 0; i < messagePointerTable.Length; i++)
            {
                messagePointerTable[i].Type = (BMDMessageType)reader.ReadInt32();
                messagePointerTable[i].Offset = reader.ReadInt32();
            }

            int actorNamePointerTableOffset = reader.ReadInt32();
            int numActors = reader.ReadInt32();

            reader.BaseStream.Seek(posFileStart + DATA_START_ADDRESS + actorNamePointerTableOffset, SeekOrigin.Begin);
            int[] actorNamePointerTable = reader.ReadInt32Array(numActors);

            _actorNames = new string[numActors];
            for (int i = 0; i < _actorNames.Length; i++)
            {
                reader.BaseStream.Seek(posFileStart + DATA_START_ADDRESS + actorNamePointerTable[i], SeekOrigin.Begin);
                _actorNames[i] = reader.ReadCString();
            }

            _messages = new BMDMessage[numMessages];
            for (int i = 0; i < _messages.Length; i++)
            {
                _messages[i] = BMDMessageFactory.GetMessage(reader, (int)posFileStart, messagePointerTable[i]);
            }
        }