Example #1
0
        public static void AssociateOpcodes()
        {
            instructions[0] = new NOP();
            instructions[1] = new PRNT();

            instructions[16] = new PUSH();
            instructions[17] = new POP();
            instructions[18] = new SAVE();
            instructions[19] = new CPY();
            instructions[20] = new RNDM();
            instructions[21] = new EMPTY();

            instructions[128] = new ADD();
            instructions[129] = new SUB();
            instructions[130] = new MUL();
            instructions[131] = new DIV();

            instructions[132] = new SUB2();
            instructions[133] = new DIV2();

            instructions[134] = new NEG();
            instructions[135] = new ABS();

            instructions[144] = new INC();
            instructions[145] = new DEC();

            instructions[64] = new JMP();
            instructions[65] = new JGZ();
            instructions[66] = new JLZ();
            instructions[67] = new JEZ();
            instructions[68] = new JNZ();
            instructions[69] = new CALL();
            instructions[70] = new RET();
            instructions[71] = new LDLOC();
            instructions[72] = new STLOC();
            instructions[73] = new LDARG();
            instructions[74] = new STARG();

            instructions[0b10100100] = new CMP();
        protected override void ReadFile(byte[] contents)
        {
            using (MemoryStream file = new MemoryStream(contents))
                using (BinaryRobloxFileReader reader = new BinaryRobloxFileReader(this, file))
                {
                    // Verify the signature of the file.
                    byte[] binSignature = reader.ReadBytes(14);
                    string signature    = Encoding.UTF7.GetString(binSignature);

                    if (signature != MagicHeader)
                    {
                        throw new InvalidDataException("Provided file's signature does not match BinaryRobloxFile.MagicHeader!");
                    }

                    // Read header data.
                    Version      = reader.ReadUInt16();
                    NumClasses   = reader.ReadUInt32();
                    NumInstances = reader.ReadUInt32();
                    Reserved     = reader.ReadInt64();

                    // Begin reading the file chunks.
                    bool reading = true;

                    Classes   = new INST[NumClasses];
                    Instances = new Instance[NumInstances];

                    while (reading)
                    {
                        try
                        {
                            var chunk = new BinaryRobloxFileChunk(reader);
                            IBinaryFileChunk handler = null;

                            switch (chunk.ChunkType)
                            {
                            case "INST":
                                handler = new INST();
                                break;

                            case "PROP":
                                handler = new PROP();
                                break;

                            case "PRNT":
                                handler = new PRNT();
                                break;

                            case "META":
                                handler = new META();
                                break;

                            case "SSTR":
                                handler = new SSTR();
                                break;

                            case "SIGN":
                                handler = new SIGN();
                                break;

                            case "END\0":
                                ChunksImpl.Add(chunk);
                                reading = false;
                                break;

                            case string unhandled:
                                Console.Error.WriteLine("BinaryRobloxFile - Unhandled chunk-type: {0}!", unhandled);
                                break;

                            default: break;
                            }

                            if (handler != null)
                            {
                                using (var readBuffer = new MemoryStream(chunk.Data))
                                {
                                    using (var dataReader = new BinaryRobloxFileReader(this, readBuffer))
                                    {
                                        chunk.Handler = handler;
                                        handler.Load(dataReader);
                                    }
                                }

                                ChunksImpl.Add(chunk);
                            }
                        }
                        catch (EndOfStreamException)
                        {
                            throw new Exception("Unexpected end of file!");
                        }
                    }
                }
        }
        public override void Save(Stream stream)
        {
            //////////////////////////////////////////////////////////////////////////
            // Generate the chunk data.
            //////////////////////////////////////////////////////////////////////////

            using (var workBuffer = new MemoryStream())
                using (var writer = new BinaryRobloxFileWriter(this, workBuffer))
                {
                    // Clear the existing data.
                    Referent = "-1";
                    ChunksImpl.Clear();

                    NumInstances = 0;
                    NumClasses   = 0;
                    SSTR         = null;

                    // Recursively capture all instances and classes.
                    writer.RecordInstances(Children);

                    // Apply the recorded instances and classes.
                    writer.ApplyClassMap();

                    // Write the INST chunks.
                    foreach (INST inst in Classes)
                    {
                        writer.SaveChunk(inst);
                    }

                    // Write the PROP chunks.
                    foreach (INST inst in Classes)
                    {
                        var props = PROP.CollectProperties(writer, inst);

                        foreach (string propName in props.Keys)
                        {
                            PROP prop = props[propName];
                            writer.SaveChunk(prop);
                        }
                    }

                    // Write the PRNT chunk.
                    var parents = new PRNT();
                    writer.SaveChunk(parents);

                    // Write the SSTR chunk.
                    if (HasSharedStrings)
                    {
                        writer.SaveChunk(SSTR, 0);
                    }

                    // Write the META chunk.
                    if (HasMetadata)
                    {
                        writer.SaveChunk(META, 0);
                    }

                    // Write the SIGN chunk.
                    if (HasSignatures)
                    {
                        writer.SaveChunk(SIGN);
                    }

                    // Write the END chunk.
                    writer.WriteChunk("END", "</roblox>");
                }

            //////////////////////////////////////////////////////////////////////////
            // Write the chunk buffers with the header data
            //////////////////////////////////////////////////////////////////////////

            using (BinaryWriter writer = new BinaryWriter(stream))
            {
                stream.Position = 0;
                stream.SetLength(0);

                writer.Write(MagicHeader
                             .Select(ch => (byte)ch)
                             .ToArray());

                writer.Write(Version);
                writer.Write(NumClasses);
                writer.Write(NumInstances);
                writer.Write(Reserved);

                foreach (BinaryRobloxFileChunk chunk in Chunks)
                {
                    if (chunk.HasWriteBuffer)
                    {
                        byte[] writeBuffer = chunk.WriteBuffer;
                        writer.Write(writeBuffer);
                    }
                }
            }
        }