Example #1
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            ScummString scummString = new ScummString(resourceId);

            var data = new List <byte>();

            byte b;

            b = reader.ReadByte();

            while (b != 0x00)
            {
                data.Add(b);
                b = reader.ReadByte();

                if (b == 0xFF)
                {
                    for (int i = 0; i < 3; ++i)
                    {
                        b = reader.ReadByte();
                        data.Add(b);
                    }
                }
            }
            scummString.Stream = new string(System.Text.Encoding.GetEncoding("IBM437").GetChars(data.ToArray()));
            return(scummString);
        }
        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);
        }
Example #3
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;
        }
        public ObcdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var result = new ObcdBlock
            {
                Header = header
            };

            long endIndex = reader.BaseStream.Position + result.Header.ContentLength;
            while (reader.BaseStream.Position < endIndex)
            {
                var childHeader = reader.ReadBlockHeader();
                switch (childHeader.HeaderName)
                {
                    case "CDHD":
                        //if (result.Room != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        reader.BaseStream.Seek(childHeader.ContentLength, SeekOrigin.Current);
                        break;
                    case "VERB":
                        if (result.Verb != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.Verb = new VerbReader().Read(childHeader, reader);
                        break;
                    case "OBNA":
                        if (result.Name != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        var bytes = reader.ReadBytes((int)childHeader.ContentLength);
                        result.Name = System.Text.Encoding.ASCII.GetString(bytes);
                        result.Name = result.Name.TrimEnd('\0');
                        break;
                    default:
                        throw new UnexpectedObjectScriptBlockException(childHeader.HeaderName);
                }
            }
            return result;
        }
Example #5
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);
        }
Example #6
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            Verb verb = new Verb(resourceId);

            int  length = 0;
            byte b      = 0xFF;

            while (b != 0x00)
            {
                b           = reader.ReadByte();
                verb.Stream = verb.Stream + (char)b;
                ++length;
                if (b == 0xFF)
                {
                    for (int i = 0; i < 3; ++i)
                    {
                        byte c = reader.ReadByte();
                        verb.Stream = verb.Stream + (char)c;
                        ++length;
                    }
                }
            }

            return(verb);
        }
Example #7
0
        public BoxmBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var pathList = new List<List<byte>>();

            long endIndex = reader.BaseStream.Position + header.ContentLength;

            List<byte> path = null;
            while (reader.BaseStream.Position < endIndex)
            {
                if (path == null)
                    path = new List<byte>();
                var curByte = reader.ReadByte();
                if (curByte != 0xff)
                {
                    path.Add(curByte);
                }
                else
                {
                    pathList.Add(path);
                    path = null;
                }
            }

            return new BoxmBlock
            {
                Header = header,
                AllPossibleBlockPaths = pathList
            };
        }
Example #8
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;
        }
Example #9
0
        private void ReadIndexFile()
        {
            var indexPath = Path.Combine(this.GamePath, string.Format("{0}.000", this.GameId));

            int blockCount = 0;

            using (var reader = new ScummBinaryReader(new ScummStream(indexPath, this.ScummVersion)))
            {
                var blockType = new string(reader.ReadChars(4));
                var itemSize  = reader.ReadUInt32BigEndian();

                while (reader.BaseStream.Position <= reader.BaseStream.Length)
                {
                    blockCount++;

                    ReadIndexBlock(reader, blockType);

                    blockType = new string(reader.ReadChars(4));
                    itemSize  = reader.ReadUInt32BigEndian();

                    if (blockCount >= 9)
                    {
                        break;
                    }
                }
            }
        }
Example #10
0
        public BoxmBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var pathList = new List <List <byte> >();

            long endIndex = reader.BaseStream.Position + header.ContentLength;

            List <byte> path = null;

            while (reader.BaseStream.Position < endIndex)
            {
                if (path == null)
                {
                    path = new List <byte>();
                }
                var curByte = reader.ReadByte();
                if (curByte != 0xff)
                {
                    path.Add(curByte);
                }
                else
                {
                    pathList.Add(path);
                    path = null;
                }
            }

            return(new BoxmBlock
            {
                Header = header,
                AllPossibleBlockPaths = pathList
            });
        }
Example #11
0
 public NlscBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return(new NlscBlock
     {
         Header = header,
         Content = reader.ReadBytes((int)header.ContentLength)
     });
 }
Example #12
0
 public TrnsBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return new TrnsBlock
     {
         Header = header,
         Content = reader.ReadBytes((int)header.ContentLength)
     };
 }
Example #13
0
 private static List<LflfBlock> ReadLflfRecords(ScummBinaryReader reader)
 {
     var list = new List<LflfBlock>();
     while (reader.BaseStream.Position < reader.BaseStream.Length)
     {
         list.Add(new LflfReader().Read(reader));
     }
     return list;
 }
Example #14
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);
        }
Example #15
0
 public RmhdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return new RmhdBlock
     {
         Header = header,
         Width = reader.ReadUInt16(),
         Height = reader.ReadUInt16(),
         NumObjects = reader.ReadUInt16(),
     };
 }
Example #16
0
 public ScummFile Read(string fileName)
 {
     using (var inputStream = new FileStream(fileName, FileMode.Open))
     {
         using (var reader = new ScummBinaryReader(inputStream, 0x69))
         {
             return(Read(reader));
         }
     }
 }
Example #17
0
        private static List <LflfBlock> ReadLflfRecords(ScummBinaryReader reader)
        {
            var list = new List <LflfBlock>();

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                list.Add(new LflfReader().Read(reader));
            }
            return(list);
        }
Example #18
0
 public RmhdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
 {
     return(new RmhdBlock
     {
         Header = header,
         Width = reader.ReadUInt16(),
         Height = reader.ReadUInt16(),
         NumObjects = reader.ReadUInt16(),
     });
 }
Example #19
0
 public ScummFile Read(string fileName)
 {
     using (var inputStream = new FileStream(fileName, FileMode.Open))
     {
         using (var reader = new ScummBinaryReader(inputStream, 0x69))
         {
             return Read(reader);
         }
     }
 }
Example #20
0
        private ScummFile Read(ScummBinaryReader reader)
        {
            var result = new ScummFile
            {
                Header     = reader.ReadBlockHeader(),
                LoffBlock  = (LoffBlock) new LoffReader().Read(reader),
                LflfBlocks = ReadLflfRecords(reader)
            };

            return(result);
        }
Example #21
0
 public ScummBlock Read(ScummBinaryReader reader)
 {
     var header = reader.ReadBlockHeader();
     var numRooms = reader.ReadByte();
     return new LoffBlock
     {
         Header = header,
         NumRooms = numRooms,
         RoomOffsets = ReadRoomOffsets(reader, numRooms)
     };
 }
Example #22
0
        private ScummFile Read(ScummBinaryReader reader)
        {
            var result = new ScummFile
            {
                Header = reader.ReadBlockHeader(),
                LoffBlock = (LoffBlock)new LoffReader().Read(reader),
                LflfBlocks = ReadLflfRecords(reader)
            };

            return result;
        }
Example #23
0
        public ScummBlock Read(ScummBinaryReader reader)
        {
            var header   = reader.ReadBlockHeader();
            var numRooms = reader.ReadByte();

            return(new LoffBlock
            {
                Header = header,
                NumRooms = numRooms,
                RoomOffsets = ReadRoomOffsets(reader, numRooms)
            });
        }
Example #24
0
 private static List<LoffBlock.RoomOffset> ReadRoomOffsets(ScummBinaryReader reader, byte numRooms)
 {
     var result = new List<LoffBlock.RoomOffset>();
     for (int i = 0; i < numRooms; i++)
     {
         var offset = new LoffBlock.RoomOffset
         {
             RoomId = reader.ReadByte(),
             Offset = reader.ReadUInt32()
         };
         result.Add(offset);
     }
     return result;
 }
Example #25
0
        private byte[] DecodeUnkCStripe(ScummBinaryReader reader, byte codingShift, int stripHeight, Color[] roomPalette)
        {
            var data = new byte[32 * stripHeight];

            var color            = (int)reader.ReadByte();
            var stripePixelsLeft = 8 * stripHeight;

            var pixelIndex = 0;
            int inc        = -1;

            while (stripePixelsLeft > 0)
            {
                var x = pixelIndex / stripHeight;
                var y = pixelIndex % stripHeight;

                var pixelAddress = y * 32 + x * 4;

                data[pixelAddress]     = roomPalette[color].R;
                data[pixelAddress + 1] = roomPalette[color].G;
                data[pixelAddress + 2] = roomPalette[color].B;
                data[pixelAddress + 3] = 255;

                stripePixelsLeft--;
                pixelIndex++;

                if (reader.ReadBit() > 0)
                {
                    if (reader.ReadBit() == 0)
                    {
                        color = reader.ReadBits(codingShift);
                        inc   = -1;
                    }

                    else
                    {
                        if (reader.ReadBit() > 0)
                        {
                            inc = -inc;
                        }

                        color += inc;
                    }
                }
            }

            reader.ResetBitCursor();

            return(data);
        }
Example #26
0
        private static List <LoffBlock.RoomOffset> ReadRoomOffsets(ScummBinaryReader reader, byte numRooms)
        {
            var result = new List <LoffBlock.RoomOffset>();

            for (int i = 0; i < numRooms; i++)
            {
                var offset = new LoffBlock.RoomOffset
                {
                    RoomId = reader.ReadByte(),
                    Offset = reader.ReadUInt32()
                };
                result.Add(offset);
            }
            return(result);
        }
Example #27
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            uint blockSize;

            if (!parameters.ContainsKey("Type") && !parameters.ContainsKey("Position"))
            {
                blockSize = reader.FindDataBlock("SCRP");
            }
            else
            {
                if (parameters.ContainsKey("Type"))
                {
                    blockSize = reader.FindDataBlock((string)parameters["Type"]);
                    if ((string)parameters["Type"] == "LSCR")
                    {
                        byte id = reader.ReadByte();
                        resourceId = String.Format("LSCRP_{0}", id);
                        --blockSize;
                    }
                    else if ((string)parameters["Type"] == "EXCD")
                    {
                        resourceId = String.Format("SCRP_{0}", 10001);
                    }
                    else if ((string)parameters["Type"] == "ENCD")
                    {
                        resourceId = String.Format("SCRP_{0}", 10002);
                    }
                }
                else
                {
                    reader.BaseStream.Position = (long)parameters["Position"];
                    blockSize  = (uint)parameters["Blocksize"];
                    blockSize += 8;
                }
            }

            // Read script Header information
            if (blockSize == 0)
            {
                throw new InvalidOperationException("Could not find the script header block.");
            }

            // Read the opcode blocks
            var data   = reader.ReadBytes((int)blockSize - 8);
            var script = new ScriptV5(resourceId, data, scriptManager, resourceManager, sceneManager, scummState, this.logFile);

            return(script);
        }
Example #28
0
        protected void ReadImageDataBlock(ScummBinaryReader reader, Image image, Color[] roomPalette)
        {
            Tuple <uint, string> findResult = reader.FindOneDataBlockOf("SMAP", "BOMP");

            if (findResult.Item1 == 0)
            {
                throw new InvalidOperationException("Could not find image data block.");
            }

            if (findResult.Item2 == "SMAP")
            {
                ReadSMAP(reader, image, roomPalette);
            }
            //else
            //    reader.BaseStream.Position += findResult.Item1 - 8;
        }
Example #29
0
        public T Load <T>(string resourceType, int resourceId, ScummBinaryReader reader, IDictionary <string, object> parameters) where T : Resource
        {
            if (this.loaders.ContainsKey(resourceType))
            {
                var loader = this.loaders[resourceType];

                // Load the resource
                string resourceIdName = string.Format("{0}_{1}", resourceType, resourceId);
                var    resource       = loader.LoadResourceData(reader, resourceIdName, parameters);

                // Return the resource
                return((T)resource);
            }
            else
            {
                throw new InvalidOperationException(string.Format("No resource loaders for blockType '{0}' were found.", resourceType));
            }
        }
Example #30
0
        public LflfBlock Read(ScummBinaryReader reader)
        {
            var result = new LflfBlock
            {
                Header = reader.ReadBlockHeader()
            };

            long endIndex = reader.BaseStream.Position + result.Header.ContentLength;

            while (reader.BaseStream.Position < endIndex)
            {
                var childHeader = reader.ReadBlockHeader();
                switch (childHeader.HeaderName)
                {
                case "ROOM":
                    if (result.Room != null)
                    {
                        throw new DuplicateBlockException(childHeader.HeaderName);
                    }
                    result.Room = new RoomReader().Read(childHeader, reader);
                    break;

                case "SCRP":
                    result.Scripts.Add(new ScriptReader().Read(childHeader, reader));
                    break;

                case "SOUN":
                    result.Sounds.Add(new SoundReader().Read(childHeader, reader));
                    break;

                case "COST":
                    result.Costumes.Add(new CostumeReader().Read(childHeader, reader));
                    break;

                case "CHAR":
                    result.Charsets.Add(new CharsetReader().Read(childHeader, reader));
                    break;

                default:
                    throw new UnexpectedBlockException(childHeader.HeaderName);
                }
            }
            return(result);
        }
Example #31
0
        public ObcdBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var result = new ObcdBlock
            {
                Header = header
            };

            long endIndex = reader.BaseStream.Position + result.Header.ContentLength;

            while (reader.BaseStream.Position < endIndex)
            {
                var childHeader = reader.ReadBlockHeader();
                switch (childHeader.HeaderName)
                {
                case "CDHD":
                    //if (result.Room != null) throw new DuplicateBlockException(childHeader.HeaderName);
                    reader.BaseStream.Seek(childHeader.ContentLength, SeekOrigin.Current);
                    break;

                case "VERB":
                    if (result.Verb != null)
                    {
                        throw new DuplicateBlockException(childHeader.HeaderName);
                    }
                    result.Verb = new VerbReader().Read(childHeader, reader);
                    break;

                case "OBNA":
                    if (result.Name != null)
                    {
                        throw new DuplicateBlockException(childHeader.HeaderName);
                    }
                    var bytes = reader.ReadBytes((int)childHeader.ContentLength);
                    result.Name = System.Text.Encoding.ASCII.GetString(bytes);
                    result.Name = result.Name.TrimEnd('\0');
                    break;

                default:
                    throw new UnexpectedObjectScriptBlockException(childHeader.HeaderName);
                }
            }
            return(result);
        }
Example #32
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);
        }
Example #33
0
        private void ReadDataFile()
        {
            // Read the entire game data file into memory for now
            var dataPath = Path.Combine(this.GamePath, string.Format("{0}.001", this.GameId));

            this.dataFileReader = new ScummBinaryReader(new ScummStream(dataPath, this.ScummVersion));

            // Read first block with room offset - other offsets are just wrong
            if (dataFileReader.FindDataBlock("LOFF") > 0)
            {
                this.roomsCount     = this.dataFileReader.ReadByte();
                this.roomsIndexList = new Dictionary <byte, uint>();

                for (int i = 0; i < this.roomsCount; i++)
                {
                    var roomId     = this.dataFileReader.ReadByte();
                    var roomOffset = this.dataFileReader.ReadUInt32();

                    this.roomsIndexList.Add(roomId, roomOffset);
                }
            }
        }
Example #34
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);
        }
Example #35
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);
        }
Example #36
0
 public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
 {
     // should never happen
     return(null);
 }
Example #37
0
        public override Resource LoadResourceData(ScummBinaryReader reader, string resourceId, IDictionary <string, object> parameters)
        {
            var charset = new Charset(resourceId);

            uint blockSize = reader.FindDataBlock("CHAR");

            if (blockSize == 0)
            {
                throw new InvalidOperationException("Could not find the script header block.");
            }

            // Load the room palette associated with the charset
            // (huge hack - I have no idea what to do when room is 0)
            if ((byte)parameters["RoomId"] == 0)
            {
                parameters["RoomId"] = (byte)10;
            }

            long keepPos     = reader.BaseStream.Position;
            var  roomPalette = this.resourceManager.Load <Room>("ROOM", (byte)parameters["RoomId"]).Palette;

            reader.BaseStream.Position = keepPos;

            // Read charset header information
            var unknown = reader.ReadBytes(6);

            byte[] colormap = new byte[16];
            colormap[0] = 0;
            for (int i = 0; i < 15; ++i)
            {
                colormap[i + 1] = reader.ReadByte();
            }

            long initPosition = reader.BaseStream.Position;

            byte numBitsPerPixel = reader.ReadByte();
            byte bitMask         = (byte)(0xFF << (8 - numBitsPerPixel));

            byte  fontHeight = reader.ReadByte();
            short numChars   = reader.ReadInt16();

            uint[] offsets = new uint[numChars];
            for (int i = 0; i < numChars; ++i)
            {
                offsets[i] = reader.ReadUInt32();
            }

            // Read each char
            for (int i = 0; i < numChars; ++i)
            {
                if (offsets[i] == 0)
                {
                    continue;
                }

                reader.BaseStream.Position = initPosition + offsets[i];

                charset.Chars[i].width  = reader.ReadByte();
                charset.Chars[i].height = reader.ReadByte();
                // a flag is needed to disable offX
                charset.Chars[i].offX = 0; reader.ReadByte();
                charset.Chars[i].offY = reader.ReadByte();
                charset.Chars[i].pic  = new Texture2D(graphicsDevice, charset.Chars[i].width, charset.Chars[i].height);

                byte[] bytes = new byte[charset.Chars[i].width * charset.Chars[i].height * 4];

                Byte bits          = reader.ReadByte();
                Byte remainingBits = 8;
                for (int y = 0; y < charset.Chars[i].height; ++y)
                {
                    for (int x = 0; x < charset.Chars[i].width; ++x)
                    {
                        long colorId = (bits & bitMask) >> (8 - numBitsPerPixel);
                        long color   = colormap[colorId];

                        byte alpha = 255;
                        if (colorId == 0)
                        {
                            alpha = 0;
                        }

                        bytes[(y * charset.Chars[i].width + x) * 4]     = roomPalette[color].R;
                        bytes[(y * charset.Chars[i].width + x) * 4 + 1] = roomPalette[color].G;
                        bytes[(y * charset.Chars[i].width + x) * 4 + 2] = roomPalette[color].B;
                        bytes[(y * charset.Chars[i].width + x) * 4 + 3] = alpha;

                        bits           = (byte)(bits << numBitsPerPixel);
                        remainingBits -= numBitsPerPixel;
                        if (remainingBits <= 0)
                        {
                            bits          = reader.ReadByte();
                            remainingBits = 8;
                        }
                    }
                }

                charset.Chars[i].pic.SetData(bytes);
            }

            return(charset);
        }
Example #38
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);
        }
Example #39
0
        private void DecodeImageData(ScummBinaryReader reader, LayeredImageData imageData, int width, int height, byte[] palette, Color[] roomPalette)
        {
            byte shift;
            byte mask;

            if (palette.Length == 16)
            {
                shift = 4;
                mask  = 0xF;
            }
            else
            {
                shift = 3;
                mask  = 0x7;
            }

            int x = 0;
            int y = 0;

            bool end = false;

            while (end == false)
            {
                var   rep = reader.ReadByte();
                var   colorPaletteIndex = (byte)(rep >> shift);
                Color color             = Color.Black;

                var roomColor = roomPalette[palette[colorPaletteIndex]];
                color.R = roomColor.R;
                color.G = roomColor.G;
                color.B = roomColor.B;

                rep &= mask;

                if (rep == 0)
                {
                    rep = reader.ReadByte();
                }

                while (rep > 0)
                {
                    if (colorPaletteIndex != 0)
                    {
                        imageData.SetPixel(x, y, color);
                    }

                    rep--;
                    y++;

                    if (y >= height)
                    {
                        y = 0;
                        x++;

                        if (x >= width)
                        {
                            end = true;
                        }
                    }
                }
            }
        }
Example #40
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);
        }
Example #41
0
        private void ReadSMAP(ScummBinaryReader reader, Image image, Color[] roomPalette)
        {
            var smapStartOffset = reader.BaseStream.Position;
            var stripesCount    = image.Width / 8;

            //  Create the texture data array
            var textureData = new byte[image.Width * image.Height * 4];

            var stripeOffsets = new uint[stripesCount];

            // Read the offset table
            for (int i = 0; i < stripesCount; i++)
            {
                var offset = reader.ReadUInt32() - 8;
                stripeOffsets[i] = offset;
            }

            // Read and decode each stripes
            for (int i = 0; i < stripesCount; i++)
            {
                reader.BaseStream.Position = smapStartOffset + stripeOffsets[i];

                var stripeHeader = reader.ReadByte();
                var codingShift  = (byte)(stripeHeader % 10);
                var encoderType  = stripeHeader / 10;

                byte[] decodedData = null;

                if (encoderType == (int)EncoderType.UnkAOpaque)
                {
                    decodedData = DecodeUnkAStripe(reader, codingShift, image.Height, roomPalette);
                }
                else if (encoderType == (int)EncoderType.UnkBOpaque)
                {
                    decodedData = DecodeUnkBStripe(reader, codingShift, image.Height, roomPalette);
                }
                else if (encoderType == (int)EncoderType.UnkCOpaque)
                {
                    decodedData = DecodeUnkCStripe(reader, codingShift, image.Height, roomPalette);
                }

                if (decodedData != null)
                {
                    int decodedDataIndex = 0;

                    for (int j = 0; j < image.Height; j++)
                    {
                        for (int k = 0; k < 8; k++)
                        {
                            var pixelIndex = i * 32 + j * image.Width * 4 + k * 4;

                            textureData[pixelIndex]     = decodedData[decodedDataIndex];
                            textureData[pixelIndex + 1] = decodedData[decodedDataIndex + 1];
                            textureData[pixelIndex + 2] = decodedData[decodedDataIndex + 2];
                            textureData[pixelIndex + 3] = decodedData[decodedDataIndex + 3];

                            decodedDataIndex += 4;
                        }
                    }
                }
            }

            image.Texture = new Microsoft.Xna.Framework.Graphics.Texture2D(graphicsDevice, image.Width, image.Height, false, Microsoft.Xna.Framework.Graphics.SurfaceFormat.Color);
            image.Texture.SetData(textureData);
        }
Example #42
0
        public RoomBlock Read(ScummBlockHeader header, ScummBinaryReader reader)
        {
            var result = new RoomBlock
            {
                Header = header
            };

            long endIndex = reader.BaseStream.Position + result.Header.ContentLength;
            while (reader.BaseStream.Position < endIndex)
            {
                var childHeader = reader.ReadBlockHeader();
                switch (childHeader.HeaderName)
                {
                    case "RMHD":
                        if (result.RoomHeader != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.RoomHeader = new RoomHeaderReader().Read(childHeader, reader);
                        break;
                    case "EPAL":
                        if (result.EgaPalette != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.EgaPalette = new EgaPaletteReader().Read(childHeader, reader);
                        break;
                    case "CLUT":
                        if (result.Clut != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.Clut = new ClutReader().Read(childHeader, reader);
                        break;
                    case "CYCL":
                        if (result.ColorCycle != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.ColorCycle = new ColorCycleReader().Read(childHeader, reader);
                        break;
                    case "TRNS":
                        if (result.Transparent != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.Transparent = new TransparentReader().Read(childHeader, reader);
                        break;
                    case "PALS":
                        if (result.Palette != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.Palette = new PaletteReader().Read(childHeader, reader);
                        break;
                    case "RMIM":
                        if (result.RoomImage != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.RoomImage = new RoomImageReader().Read(childHeader, reader);
                        break;
                    case "OBIM":
                        result.ObjImages.Add(new ObjImageReader().Read(childHeader, reader));
                        break;
                    case "OBCD":
                        result.ObjectScripts.Add(new ObjectScriptReader().Read(childHeader, reader));
                        break;
                    case "EXCD":
                        if (result.ExitScript != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.ExitScript = new ExitScriptReader().Read(childHeader, reader);
                        break;
                    case "ENCD":
                        if (result.EntryScript != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.EntryScript = new EntryScriptReader().Read(childHeader, reader);
                        break;
                    case "NLSC":
                        if (result.NumScripts != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.NumScripts = new NumScriptsReader().Read(childHeader, reader);
                        break;
                    case "LSCR":
                        result.LocalScripts.Add(new LocalScriptReader().Read(childHeader, reader));
                        break;
                    case "BOXD":
                        if (result.BoxData != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.BoxData = new BoxDataReader().Read(childHeader, reader);
                        break;
                    case "BOXM":
                        if (result.BoxMatrix != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.BoxMatrix = new BoxMatrixReader().Read(childHeader, reader);
                        break;
                    case "SCAL":
                        if (result.ScaleSlots != null) throw new DuplicateBlockException(childHeader.HeaderName);
                        result.ScaleSlots = new ScaleSlotsReader().Read(childHeader, reader);
                        break;
                    default:
                        throw new UnexpectedRoomBlockException(childHeader.HeaderName);
                }
            }
            return result;
        }