Ejemplo n.º 1
0
        private IEnumerable <ProgramState> ProcessSwt(ILInstruction instruction, ProgramState next)
        {
            var result = new List <ProgramState>();

            var symbolicTableSlot = next.Stack.Pop();
            var symbolicValue     = next.Stack.Pop();

            instruction.Dependencies.AddOrMerge(0, symbolicTableSlot);
            instruction.Dependencies.AddOrMerge(1, symbolicValue);

            var annotation = new JumpAnnotation
            {
                InferredPopCount  = instruction.Dependencies.Count,
                InferredPushCount = 0
            };

            ulong tableAddress = symbolicTableSlot.InferStackValue().U8;

            var reader = new MemoryStreamReader(KoiStream.Data);

            reader.Position = (long)tableAddress - 2;

            ushort count = reader.ReadUInt16();

            for (int i = 0; i < count; i++)
            {
                int   relativeOffset = reader.ReadInt32();
                ulong nextIp         = (ulong)((long)next.IP + relativeOffset);

                Logger.Debug(Tag, $"Inferred edge IL_{instruction.Offset:X4} -> IL_{nextIp:X4}");

                var caseState = next.Copy();
                caseState.IP = nextIp;
                result.Add(caseState);

                annotation.InferredJumpTargets.Add(nextIp);
            }

            result.Add(next);
            instruction.Annotation = annotation;
            return(result);
        }
Ejemplo n.º 2
0
        private void ParseSection(SubChunk section, ReadOnlyMemory <byte> data)
        {
            var reader = new MemoryStreamReader(data);

            var version = reader.ReadByte();

            if (version != 8)
            {
                throw new Exception("Wrong chunk version");
            }

            var storageSize = reader.ReadByte();

            for (int storage = 0; storage < storageSize; storage++)
            {
                byte paletteAndFlag = (byte)reader.ReadByte();
                bool isRuntime      = (paletteAndFlag & 1) != 0;
                if (isRuntime)
                {
                    throw new Exception("Can't use runtime for persistent storage.");
                }
                int bitsPerBlock  = paletteAndFlag >> 1;
                int blocksPerWord = (int)Math.Floor(32d / bitsPerBlock);
                int wordCount     = (int)Math.Ceiling(4096d / blocksPerWord);

                long blockIndex = reader.Position;
                reader.Position += wordCount * 4;

                int paletteSize = reader.ReadInt32();

                var palette = new Dictionary <int, int>();
                for (int j = 0; j < paletteSize; j++)
                {
                    var file = new NbtFile
                    {
                        BigEndian = false,
                        UseVarInt = false
                    };
                    file.LoadFromStream(reader, NbtCompression.None);
                    var tag = (NbtCompound)file.RootTag;

                    Block block = BlockFactory.GetBlockByName(tag["name"].StringValue);
                    if (block != null && block.GetType() != typeof(Block) && !(block is Air))
                    {
                        List <IBlockState> blockState = ReadBlockState(tag);
                        block.SetState(blockState);
                    }
                    else
                    {
                        block = new Air();
                    }

                    palette.Add(j, block.GetRuntimeId());
                }

                long nextStore = reader.Position;
                reader.Position = blockIndex;

                int position = 0;
                for (int wordIdx = 0; wordIdx < wordCount; wordIdx++)
                {
                    uint word = reader.ReadUInt32();
                    for (int block = 0; block < blocksPerWord; block++)
                    {
                        if (position >= 4096)
                        {
                            continue;                                           // padding bytes
                        }
                        int state = (int)((word >> ((position % blocksPerWord) * bitsPerBlock)) & ((1 << bitsPerBlock) - 1));
                        int x     = (position >> 8) & 0xF;
                        int y     = position & 0xF;
                        int z     = (position >> 4) & 0xF;
                        if (state > palette.Count)
                        {
                            Log.Error($"Got wrong state={state} from word. bitsPerBlock={bitsPerBlock}, blocksPerWord={blocksPerWord}, Word={word}");
                        }

                        if (storage == 0)
                        {
                            section.SetBlockByRuntimeId(x, y, z, palette[state]);
                        }
                        else
                        {
                            section.SetLoggedBlockByRuntimeId(x, y, z, palette[state]);
                        }
                        position++;
                    }
                }
                reader.Position = nextStore;
            }
        }