Esempio n. 1
0
        public BoxdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var numBlocks = reader.ReadUInt16();
            var boxList   = new List <BoxdBlock.Box>();

            for (int i = 0; i < numBlocks; i++)
            {
                var box = new BoxdBlock.Box()
                {
                    UpperLeftX  = reader.ReadUInt16(),
                    UpperLeftY  = reader.ReadUInt16(),
                    UpperRightX = reader.ReadUInt16(),
                    UpperRightY = reader.ReadUInt16(),
                    LowerRightX = reader.ReadUInt16(),
                    LowerRightY = reader.ReadUInt16(),
                    LowerLeftX  = reader.ReadUInt16(),
                    LowerLeftY  = reader.ReadUInt16(),
                    Mask        = reader.ReadByte(),
                    Flags       = reader.ReadByte(),
                    Scale       = reader.ReadUInt16()
                };
                boxList.Add(box);
            }

            var result = new BoxdBlock
            {
                Header  = header,
                BoxList = boxList
            };

            return(result);
        }
Esempio n. 2
0
        public BoxdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var numBlocks = reader.ReadUInt16();
            var boxList = new List<BoxdBlock.Box>();
            for (int i = 0; i < numBlocks; i++)
            {
                var box = new BoxdBlock.Box()
                {
                    UpperLeftX = reader.ReadUInt16(),
                    UpperLeftY = reader.ReadUInt16(),
                    UpperRightX = reader.ReadUInt16(),
                    UpperRightY = reader.ReadUInt16(),
                    LowerRightX = reader.ReadUInt16(),
                    LowerRightY = reader.ReadUInt16(),
                    LowerLeftX = reader.ReadUInt16(),
                    LowerLeftY = reader.ReadUInt16(),
                    Mask = reader.ReadByte(),
                    Flags = reader.ReadByte(),
                    Scale = reader.ReadUInt16()
                };
                boxList.Add(box);
            }

            var result = new BoxdBlock
            {
                Header = header,
                BoxList = boxList
            };
            return result;
        }
Esempio n. 3
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            reader.FindDataBlockNoInfo("OBCD");

            // read header
            uint   blockSize = reader.FindDataBlock("CDHD");
            UInt16 id        = reader.ReadUInt16();

            var obj  = ResourceManager.FindObject(id);
            var data = reader.ReadBytes((int)blockSize - 10);

            // read verb block
            blockSize = reader.FindDataBlock("VERB");
            long verbPos = reader.BaseStream.Position - 8;

            // read verbs and offsets
            byte[]   verbs   = new byte[100];
            UInt16[] offsets = new UInt16[100];

            int totalVerbs = 0;

            verbs[totalVerbs] = reader.ReadByte();
            while (verbs[totalVerbs] != 0)
            {
                offsets[totalVerbs] = reader.ReadUInt16();
                verbs[++totalVerbs] = reader.ReadByte();
            }
            // final offset found reading the next block - needed for blocksize
            reader.FindDataBlockNoInfo("OBNA");
            long endPos = reader.BaseStream.Position - 8;

            // read object name
            byte a = reader.ReadByte();

            while (a != 0)
            {
                obj.Name += (char)a;
                a         = reader.ReadByte();
            }
            long backupPos = reader.BaseStream.Position;

            // load verb scripts
            for (int i = 0; i < totalVerbs; ++i)
            {
                long startPos = verbPos + offsets[i];
                uint size     = (uint)(endPos - startPos);

                obj.VerbScript[verbs[i]] =
                    (ScriptV5)resourceManager.Load <Script>("SCRP", id, reader, new Dictionary <string, object>()
                {
                    { "Position", startPos }, { "Blocksize", size }
                });
            }
            reader.BaseStream.Position = backupPos;

            return(obj);
        }
Esempio n. 4
0
 public RmhdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return new RmhdBlock
     {
         Header = header,
         Width = reader.ReadUInt16(),
         Height = reader.ReadUInt16(),
         NumObjects = reader.ReadUInt16(),
     };
 }
Esempio n. 5
0
 public RmhdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return(new RmhdBlock
     {
         Header = header,
         Width = reader.ReadUInt16(),
         Height = reader.ReadUInt16(),
         NumObjects = reader.ReadUInt16(),
     });
 }
Esempio n. 6
0
        public VerbBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            //var bytes = reader.ReadBytes(100).Select(x => (char) x);
            List<VerbBlock.VerbEntry> verbEntries = new List<VerbBlock.VerbEntry>();
            while (true)
            {
                var verb = reader.ReadByte();
                if (verb == 0)
                    break;
                verbEntries.Add(new VerbBlock.VerbEntry
                {
                    Verb = verb,
                    Offset = reader.ReadUInt16()
                });
            }

            uint endIndex = header.ContentLength;
            foreach (var verb in verbEntries.OrderByDescending(x => x.Offset))
            {
                verb.Length = endIndex - (verb.Offset - 8);
                verb.Content = reader.ReadBytes((int)verb.Length);
                endIndex = (uint)(verb.Offset - 8);
            }

            var result = new VerbBlock
            {
                Header = header,
                VerbEntries = verbEntries
            };
            return result;
        }
Esempio n. 7
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            reader.FindDataBlockNoInfo("OBIM");
            // read header
            uint blockSize = reader.FindDataBlock("IMHD");

            UInt16 id  = reader.ReadUInt16();
            var    obj = ResourceManager.FindObject(id);

            UInt16 numImages = reader.ReadUInt16();
            UInt16 numZs     = reader.ReadUInt16();
            Byte   flags     = reader.ReadByte();
            Byte   unknown   = reader.ReadByte();
            UInt16 x         = reader.ReadUInt16();
            UInt16 y         = reader.ReadUInt16();
            UInt16 width     = reader.ReadUInt16();
            UInt16 height    = reader.ReadUInt16();

            obj.Position = new Vector2(x, y);
            obj.Image    = new Image(width, height);

            var roomPalette = (Color[])parameters["RoomPalette"];

            for (int i = 0; i < numImages; ++i)
            {
                string blockName = String.Format("IM{0:X2}", i + 1);
                if (reader.FindDataBlock(blockName) == 0)
                {
                    throw new InvalidOperationException("Could not find image block.");
                }
                ReadImageDataBlock(reader, obj.Image, roomPalette);
            }

            return(obj.Image);
        }
Esempio n. 8
0
        private ResourceIndexEntry[] ReadResourceReferenceList(ScummBinaryReader reader, ref ushort itemsCount)
        {
            itemsCount = reader.ReadUInt16();

            var resourceReferenceList = new ResourceIndexEntry[itemsCount];
            var roomIdList            = new byte[itemsCount];

            for (int i = 0; i < itemsCount; i++)
            {
                roomIdList[i] = reader.ReadByte();
            }
            for (int i = 0; i < itemsCount; i++)
            {
                var resourceOffset = reader.ReadUInt32();
                resourceReferenceList[i] = new ResourceIndexEntry(roomIdList[i], resourceOffset);
            }

            return(resourceReferenceList);
        }
Esempio n. 9
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            var image       = new Image((int)parameters["Width"], (int)parameters["Height"]);
            var roomPalette = (Color[])parameters["RoomPalette"];

            // Read the image header
            if (reader.FindDataBlock("RMIH", (uint)parameters["RoomOffset"]) == 0)
            {
                throw new InvalidOperationException("Could not find the room background header block.");
            }

            var zbufferCount = reader.ReadUInt16();

            // TODO: Add code to take into account multiple image blocks (object images)
            if (reader.FindDataBlock("IM00") == 0)
            {
                throw new InvalidOperationException("Could not find image block.");
            }

            ReadImageDataBlock(reader, image, roomPalette);

            return(image);
        }
Esempio n. 10
0
        public VerbBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            //var bytes = reader.ReadBytes(100).Select(x => (char) x);
            List <VerbBlock.VerbEntry> verbEntries = new List <VerbBlock.VerbEntry>();

            while (true)
            {
                var verb = reader.ReadByte();
                if (verb == 0)
                {
                    break;
                }
                verbEntries.Add(new VerbBlock.VerbEntry
                {
                    Verb   = verb,
                    Offset = reader.ReadUInt16()
                });
            }


            uint endIndex = header.ContentLength;

            foreach (var verb in verbEntries.OrderByDescending(x => x.Offset))
            {
                verb.Length  = endIndex - (verb.Offset - 8);
                verb.Content = reader.ReadBytes((int)verb.Length);
                endIndex     = (uint)(verb.Offset - 8);
            }

            var result = new VerbBlock
            {
                Header      = header,
                VerbEntries = verbEntries
            };

            return(result);
        }
Esempio n. 11
0
        private CostumeAnimation LoadAnimation(ScummBinaryReader reader, string resourceId, int animationIndex, long startOffset, ushort[] animationOffsets, ushort[] limbOffsets, ushort animationCommandOffset, byte[] palette, Color[] roomPalette, bool containsRedirection, bool mirror)
        {
            if (animationOffsets[animationIndex] == 0)
            {
                return(null);
            }

            reader.BaseStream.Position = startOffset + animationOffsets[animationIndex];

            var costumeAnimation = new CostumeAnimation();

            costumeAnimation.IsMirrored = mirror;

            var currentFrameIndex      = 0;
            var framesCount            = 0;
            var startAnimationPosition = reader.BaseStream.Position;

            while (currentFrameIndex < framesCount || currentFrameIndex == 0)
            {
                var mask = reader.ReadUInt16();

                var costumeFrame = new CostumeFrame();
                var imageData    = new LayeredImageData();

                var i = 0;

                do
                {
                    if ((mask & 0x8000) != 0)
                    {
                        var startAnimationCommandOffset = reader.ReadUInt16();

                        if (startAnimationCommandOffset != 0xFFFF)
                        {
                            var flags = reader.ReadByte();

                            var loop     = flags & 0x8000;
                            var endFrame = flags & 0x7F;

                            if (currentFrameIndex == 0 && framesCount == 0)
                            {
                                framesCount = Math.Max(framesCount, endFrame) + 1;
                            }

                            var oldStreamPosition = reader.BaseStream.Position;
                            reader.BaseStream.Position = startOffset + animationCommandOffset + startAnimationCommandOffset + Math.Min(currentFrameIndex, endFrame);

                            var animationCommandValue = reader.ReadByte();

                            if (animationCommandValue == 0x71)
                            {
                                // TODO: Handle special commands (sounds, etc.)
                            }

                            else if (animationCommandValue == 0x7A)
                            {
                                // TODO: Implement start command
                            }

                            else if (animationCommandValue == 0x79)
                            {
                                // TODO: Implement stopped command
                            }

                            else
                            {
                                reader.BaseStream.Position = startOffset + limbOffsets[i] + animationCommandValue * 2;
                                var pictOffset = reader.ReadUInt16();

                                reader.BaseStream.Position = startOffset + pictOffset;

                                var width     = reader.ReadUInt16();
                                var height    = reader.ReadUInt16();
                                var relativeX = reader.ReadInt16();
                                var relativeY = reader.ReadInt16();
                                var movementX = reader.ReadInt16();
                                var movementY = reader.ReadInt16();

                                if (containsRedirection)
                                {
                                    var redirectionLimb = reader.ReadByte();
                                    var redirectionPict = reader.ReadByte();
                                }

                                imageData.CreateLayer(width, height, new Vector2(relativeX, relativeY));

                                DecodeImageData(reader, imageData, width, height, palette, roomPalette);
                            }

                            reader.BaseStream.Position = oldStreamPosition;
                        }
                    }

                    mask = (ushort)(mask << 1);
                    i++;
                } while ((mask & 0xFFFF) != 0);

                costumeFrame.FrameType = CostumeFrameType.Frame;

                // TODO: Fill offset and movement vector

                var textureData = imageData.GetBytes();
                costumeFrame.Data = new Microsoft.Xna.Framework.Graphics.Texture2D(this.graphicsDevice, imageData.Width, imageData.Height, false, Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color);
                costumeFrame.Data.SetData(textureData);

                costumeAnimation.Frames.Add(costumeFrame);

                if (!Directory.Exists("DebugAnims\\" + resourceId))
                {
                    Directory.CreateDirectory("DebugAnims\\" + resourceId);
                }
                costumeFrame.Data.SaveAsPng(File.Create(string.Format("DebugAnims\\" + resourceId + "\\Anim{0}_{1}.png", animationIndex, currentFrameIndex)), costumeFrame.Data.Width, costumeFrame.Data.Height);

                reader.BaseStream.Position = startAnimationPosition;
                currentFrameIndex++;
            }

            return(costumeAnimation);
        }
Esempio n. 12
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            // TODO: If the anim is mirrored, point to the same textures and do a matrix transform while rendering the costume
            var costume = new Costume(resourceId);

            // Read Room Header information
            if (reader.FindDataBlock("COST") == 0)
            {
                throw new InvalidOperationException("Could not find the costume header block.");
            }

            reader.BaseStream.Position -= 6;
            var startOffset = reader.BaseStream.Position;

            var size = reader.ReadUInt32();
            var test = ((char)reader.ReadByte()).ToString() + ((char)reader.ReadByte()).ToString();

            var animationsCount = reader.ReadByte();

            var format              = reader.ReadByte();
            var paletteSize         = ((format & 0x7F) == 0x58 || (format & 0x7F) == 0x60) ? 16 : 32;
            var containsRedirection = ((format & 0x7E) == 0x60);
            var mirrorWestPositions = (format & 0x80) == 0;

            // TODO: Decode bit 7

            // TODO : Read the full palette
            var palette = new byte[paletteSize];

            for (int i = 0; i < paletteSize; i++)
            {
                palette[i] = reader.ReadByte();
            }

            var animationCommandOffset = reader.ReadUInt16();

            // Read limb offsets
            var limbOffsets = new ushort[16];

            for (int i = 0; i < 16; i++)
            {
                limbOffsets[i] = reader.ReadUInt16();
            }

            // Read animation offsets
            var animationOffsets = new ushort[animationsCount];

            for (int i = 0; i < animationOffsets.Length; i++)
            {
                animationOffsets[i] = reader.ReadUInt16();
            }

            // Load the room palette associated with the costume
            // (huge hack - I have no idea what to do when room is 0)
            if ((byte)parameters["RoomId"] == 0)
            {
                parameters["RoomId"] = (byte)10;
            }
            var roomPalette = this.resourceManager.Load <Room>("ROOM", (byte)parameters["RoomId"]).Palette;

            for (int i = 4; i < animationsCount; i++)
            {
                try
                {
                    var animation = LoadAnimation(reader, resourceId, i, startOffset, animationOffsets, limbOffsets, animationCommandOffset, palette, roomPalette, containsRedirection, (i % 4) == 0 && mirrorWestPositions);
                    costume.Animations.Add(animation);
                }
                // TODO: Remove the empty catch later
                catch { }
            }

            return(costume);
        }
Esempio n. 13
0
        private void ReadIndexBlock(ScummBinaryReader reader, string blockType)
        {
            if (blockType == "RNAM")
            {
                byte roomId = reader.ReadByte();
                while (roomId != 0)
                {
                    var roomNameData = reader.ReadBytes(9);
                    var roomName     = string.Empty;

                    for (int i = 0; i < roomNameData.Length; i++)
                    {
                        roomName += (char)(roomNameData[i] ^ 0xFF);
                    }

                    roomId = reader.ReadByte();
                }
            }

            else if (blockType == "MAXS")
            {
                var variablesCount = reader.ReadUInt16();

                // Skip 2 bytes
                reader.ReadUInt16();

                uint bitVariablesCount     = reader.ReadUInt16();
                uint localObjectsCount     = reader.ReadUInt16();
                uint newNamesCount         = reader.ReadUInt16();
                uint charsetsCount         = reader.ReadUInt16();
                uint verbsCount            = reader.ReadUInt16();
                uint arraysCount           = reader.ReadUInt16();
                uint inventoryObjectsCount = reader.ReadUInt16();
            }

            else if (blockType == "DROO")
            {
                // just read, not keeping anything besides roomsCount
                ReadResourceReferenceList(reader, ref roomsCount);
            }

            else if (blockType == "DSCR")
            {
                this.scriptsIndexList = ReadResourceReferenceList(reader, ref scriptsCount);
            }

            else if (blockType == "DSOU")
            {
                this.soundsIndexList = ReadResourceReferenceList(reader, ref soundsCount);
            }

            else if (blockType == "DCOS")
            {
                this.costumesIndexList = ReadResourceReferenceList(reader, ref costumesCount);
            }

            else if (blockType == "DCHR")
            {
                this.charsetsIndexList = ReadResourceReferenceList(reader, ref charsetsCount);
            }

            else if (blockType == "DOBJ")
            {
                uint itemsCount = reader.ReadUInt16();
                objects = new Object[itemsCount];

                for (int i = 0; i < itemsCount; i++)
                {
                    objects[i]            = new Object();
                    objects[i].Id         = (UInt16)i;
                    objects[i].OwnerState = reader.ReadByte();
                }
                for (int i = 0; i < itemsCount; i++)
                {
                    objects[i].ClassData = reader.ReadUInt32();
                }
            }
            else if (blockType == "AARY")
            {
            }
            else
            {
                //throw new InvalidOperationException(string.Format("Cannot read block of type '{0}' in the index file.", blockType));
            }
        }
Esempio n. 14
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            var room       = new Room(resourceId);
            var roomOffset = (uint)reader.BaseStream.Position;

            // Read Room Header information
            if (reader.FindDataBlock("RMHD", roomOffset) == 0)
            {
                throw new InvalidOperationException("Could not find the room header block.");
            }

            var width        = reader.ReadUInt16();
            var height       = reader.ReadUInt16();
            var objectsCount = reader.ReadUInt16();

            // Read palette data
            if (reader.FindDataBlock("CLUT", roomOffset) == 0)
            {
                throw new InvalidOperationException("Could not find the room palette block.");
            }

            // Load only the first palette for now
            room.Palette = new Color[256];
            for (int i = 0; i < 256; ++i)
            {
                room.Palette[i].R = reader.ReadByte();
                room.Palette[i].G = reader.ReadByte();
                room.Palette[i].B = reader.ReadByte();
            }

            // Read background image
            room.BackgroundImage = ResourceManager.Load <Image>("RMIM", new Dictionary <string, object>()
            {
                { "Width", (int)width }, { "Height", (int)height }, { "RoomOffset", roomOffset }, { "RoomPalette", room.Palette }
            });

            room.Objects = new Object[objectsCount];

            Image[] images = new Image[objectsCount];
            if (objectsCount == 13)
            {
                objectsCount -= 1;
            }

            if (objectsCount == 90)
            {
                objectsCount -= 7;
            }

            for (int i = 0; i < objectsCount; ++i)
            {
                ResourceManager.Load <Image>("OBIM", new Dictionary <string, object>()
                {
                    { "RoomPalette", room.Palette }
                });
            }

            if (objectsCount == 12)
            {
                objectsCount += 1;
            }

            if (objectsCount == 83)
            {
                objectsCount += 7;
            }

            for (int i = 0; i < objectsCount; ++i)
            {
                ResourceManager.Load <Object>("OBJC", new Dictionary <string, object>());
            }

            // Read entry/exit scripts
            room.ExitScript = ResourceManager.Load <Script>("SCRP", new Dictionary <string, object>()
            {
                { "Type", "EXCD" }
            });
            room.EntryScript = ResourceManager.Load <Script>("SCRP", new Dictionary <string, object>()
            {
                { "Type", "ENCD" }
            });

            // Read local script
            if (reader.FindDataBlock("NLSC") != 0)
            {
                byte totalLocal = reader.ReadByte();
                byte padding    = reader.ReadByte();
                if (totalLocal != 0)
                {
                    room.Scripts = new Script[totalLocal];
                    for (int i = 0; i < totalLocal; ++i)
                    {
                        room.Scripts[i] = resourceManager.Load <Script>("SCRP", new Dictionary <string, object>()
                        {
                            { "Type", "LSCR" }
                        });
                    }
                }
            }

            return(room);
        }