public override void Load(BinaryReaderEx reader)
        {
            BasePosition      = reader.BaseStream.Position;
            Type              = reader.ReadInt16();
            Unk1              = reader.ReadInt16();
            Unk2              = reader.ReadInt16();
            NumOffsets        = reader.ReadInt16();
            StringTableOffset = reader.ReadInt32();

            for (var i = 0; i < NumOffsets; i++)
            {
                Offsets.Add(reader.ReadInt32());
            }

            if (StringTableOffset != 0)
            {
                reader.BaseStream.Position = BasePosition + StringTableOffset;
                StringTableBase            = BasePosition + StringTableOffset;
                NumStrings = reader.ReadInt32();

                for (var i = 0; i < NumStrings; i++)
                {
                    StringOffsets.Add(reader.ReadInt32());
                }

                for (var i = 0; i < NumStrings; i++)
                {
                    reader.BaseStream.Position = StringTableBase + StringOffsets[i] + 4;
                    Strings.Add(reader.ReadNullTerminatedString());
                }
            }

            for (var i = 0; i < NumOffsets; i++)
            {
                reader.BaseStream.Position = BasePosition + this.Offsets[i];
                short            type = reader.ReadInt16();
                SparkleChunkBase c;
                switch (type)
                {
                case 1:
                    c = new SparkleChunk1();
                    break;

                case 2:
                    c = new SparkleChunk2();
                    break;

                case 3:
                    c = new SparkleChunk3();
                    break;

                default:
                    throw new InvalidOperationException("Unexpected Sparkle Chunk Type: " + type);
                }

                reader.BaseStream.Position = BasePosition + this.Offsets[i];
                c.Load(reader);
                this.Chunks.Add(c);
            }
        }
        private void ReadScriptSCI1_1()
        {
            // https://github.com/scummvm/scummvm/blob/master/engines/sci/engine/script.cpp#L390
            // https://github.com/icefallgames/SCICompanion/blob/master/SCICompanionLib/Src/Compile/CompiledScript.cpp#L226
            List <ushort> exportsTO       = new List <ushort>();
            List <ushort> exportedObjInst = new List <ushort>();
            var           heapRes         = Package.GetResouce(ResType.Heap, Resource.Volumes[0].Num);

            using (var stream = new MemoryStream(SourceData.Length))
            {
                stream.Write(SourceData, 0, SourceData.Length);
                stream.Seek(0, SeekOrigin.Begin);

                var endOfStringOffset = stream.ReadUShortBE();
                var heapPoints        = ReadOffsets(stream, endOfStringOffset);
                stream.Seek(4, SeekOrigin.Current);

                var exportsCount = stream.ReadUShortBE();
                for (int i = 0; i < exportsCount; i++)
                {
                    var isHeapPointer = heapPoints.Contains((ushort)stream.Position);
                    var exportOffset  = stream.ReadUShortBE();

                    exportsTO.Add(exportOffset);
                    if (isHeapPointer)
                    {
                        exportedObjInst.Add(exportOffset);
                    }
                }

                List <LocalVar> localVars = new List <LocalVar>();
                var             heapData  = heapRes.GetContent(_translated);
                using (var heap = new MemoryStream(heapData))
                {
                    var stringOffset = heap.ReadUShortBE();
                    StringOffsets = ReadOffsets(heap, stringOffset);
                    var localsCount = heap.ReadUShortBE();
                    for (int i = 0; i < localsCount; i++)
                    {
                        bool   isObjectOrString = StringOffsets.Contains((ushort)heap.Position);
                        ushort w = heap.ReadUShortBE();
                        localVars.Add(new LocalVar {
                            Value = w, IsObjectOrString = isObjectOrString
                        });
                    }


                    while (true)
                    {
                        var magic = heap.ReadUShortBE();
                        if (magic == 0)
                        {
                            break;
                        }

                        if (magic != 0x1234)
                        {
                            throw new Exception("Wrong script format");
                        }

                        var obj = new Object1_1(this);
                        obj.Read(stream, heap);
                        Objects.Add(obj);
                    }

                    do
                    {
                        var           offs          = (ushort)heap.Position;
                        var           str           = heap.ReadString(Resource.GameEncoding);
                        List <ushort> stringsOffset = new List <ushort>();
                        if (str.Length > 0 || heap.Position < stringOffset)
                        {
                            stringsOffset.Add(offs);
                            Strings.Add(str);
                        }
                    }while (heap.Position < stringOffset);
                }
            }
        }
Beispiel #3
0
        private void ReadScriptSCI1_1()
        {
            // https://github.com/scummvm/scummvm/blob/master/engines/sci/engine/script.cpp#L390
            // https://github.com/icefallgames/SCICompanion/blob/master/SCICompanionLib/Src/Compile/CompiledScript.cpp#L226
            var heapRes = Package.GetResource(ResType.Heap, Resource.Number);

            using var stream = new MemoryStream(_sourceData.Length);
            stream.Write(_sourceData, 0, _sourceData.Length);
            stream.Seek(0, SeekOrigin.Begin);

            var endOfStringOffset = stream.ReadUShortBE();
            var heapPoints        = ReadOffsets(stream, endOfStringOffset);

            stream.Seek(4, SeekOrigin.Current);

            var exportsCount = stream.ReadUShortBE();

            ExportsOffsets       = new ushort[exportsCount];
            ExportsOffsetsIsHeap = new bool[exportsCount];
            for (int i = 0; i < exportsCount; i++)
            {
                var isHeapPointer = heapPoints.Contains((ushort)stream.Position);
                var exportOffset  = stream.ReadUShortBE();

                ExportsOffsets[i] = exportOffset;
                if (isHeapPointer)
                {
                    ExportsOffsetsIsHeap[i] = true;
                }
            }

            var heapData = heapRes.GetContent();

            using var heap = new MemoryStream(heapData);

            var stringOffset = heap.ReadUShortBE();

            StringOffsets = ReadOffsets(heap, stringOffset);
            var localsCount = heap.ReadUShortBE();

            for (int i = 0; i < localsCount; i++)
            {
                bool   isObjectOrString = StringOffsets.Contains((ushort)heap.Position);
                ushort w = heap.ReadUShortBE();
                localVars.Add(new LocalVar {
                    Value = w, IsObjectOrString = isObjectOrString
                });
            }


            while (true)
            {
                var offset = (ushort)heap.Position;
                var magic  = heap.ReadUShortBE();
                if (magic == 0)
                {
                    break;
                }

                if (magic != 0x1234)
                {
                    throw new Exception("Wrong script format");
                }

                var obj = new Object1_1(this, heapData, offset);
                obj.Read(stream, heap);
                Objects.Add(obj);

                for (int i = 0; i < exportsCount; i++)
                {
                    if (ExportsOffsetsIsHeap[i] && ExportsOffsets[i] == obj.Offset)
                    {
                        obj.ExportInd = i;
                    }
                }
            }

            do
            {
                var offs = (ushort)heap.Position;
                var str  = heap.ReadString(Resource.GameEncoding);
                //List<ushort> stringsOffset = new List<ushort>();
                if (str.Length > 0 || heap.Position < stringOffset)
                {
                    //stringsOffset.Add(offs);
                    Strings.Add(str);
                }
            }while (heap.Position < stringOffset);
        }