Beispiel #1
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;
 }
Beispiel #2
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);
        }
        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);
        }
Beispiel #4
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);
        }
Beispiel #5
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);
        }
Beispiel #6
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);
        }
        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));
            }
        }