Esempio n. 1
0
        public AGSGameData()
        {
            setup                  = new AGSGameSetupStruct();
            save_guid              = new char[0];
            save_extension         = new char[0];
            save_folder            = new char[0];
            font_flags             = new byte[0];
            font_outlines          = new byte[0];
            sprite_flags           = new byte[0];
            inventoryItems         = new AGSInventoryItem[0];
            cursors                = new AGSCursorInfo[0];
            dictionary             = new AGSDictionary();
            globalScript           = new AGSScript();
            dialogScript           = new AGSScript();
            scriptModules          = new AGSScript[0];
            views                  = new AGSView[0];
            characters             = new AGSCharacter[0];
            globalMessages         = new string[0];
            dialogs                = new AGSDialog[0];
            audioStorage           = new AGSAudioStorage();
            customPropertiesSchema = new AGSCustomProperiesSchema();
            roomsDebugInfo         = new AGSRoomDebugInfo[0];
            globalvars             = new AGSInteractionVariable[0];

            views272         = new AGSView272[0];
            oldDialogStrings = new List <string>();

            guis             = new AGSGUI[0];
            buttons          = new AGSGUIButton[0];
            labels           = new AGSGUILabel[0];
            inventoryWindows = new AGSGUIInventoryWindow[0];
            sliders          = new AGSGUISlider[0];
            textboxes        = new AGSGUITextBox[0];
            listboxes        = new AGSGUIListBox[0];
        }
        private static int GetExportIndex(AGSScript script, int offset)
        {
            int index = -1;

            for (int i = 0; i < script.Exports.Length; ++i)
            {
                int functionOffset = script.Exports[i].Pointer & 0x00FFFFFF;
                if (functionOffset == offset)
                {
                    index = i;
                    break;
                }
            }

            Debug.Assert(index != -1);
            return(index);
        }
        private static int GetStringIndex(AGSScript script, int offset)
        {
            int acc = 0;
            int i   = 0;

            for (; i < script.Strings.Length; ++i)
            {
                if (acc == offset)
                {
                    break;
                }

                acc += script.Strings[i].Length + 1;
            }

            Debug.Assert(acc == offset);
            return(i);
        }
Esempio n. 4
0
        public void LoadFromStream(BinaryReader r)
        {
            // verify signature
            char[] dta_sig        = r.ReadChars(DTA_SIGNATURE.Length);
            string dta_sig_string = new string(dta_sig);

            Debug.Assert(DTA_SIGNATURE == dta_sig_string);

            // parse dta header
            Int32  dta_version    = r.ReadInt32();
            Int32  strlen         = r.ReadInt32();
            string engine_version = r.ReadFixedCString(strlen);

            // parse capability strings
            if (dta_version >= 48) // 3.4.1
            {
                Int32 capabilities_count = r.ReadInt32();
                for (int i = 0; i < capabilities_count; ++i)
                {
                    string capability = r.ReadString();
                }
            }

            // parse game setup struct base
            AGSAlignedStream ar = new AGSAlignedStream(r);

            setup.LoadFromStream(ar, dta_version);

            if (dta_version > 32) // 3.x
            {
                // parse save game info
                save_guid      = r.ReadChars(40);
                save_extension = r.ReadChars(20);
                save_folder    = r.ReadChars(50);
            }

            // parse font info
            if (dta_version < 50) // 3.5
            {
                font_flags    = r.ReadBytes(setup.fonts_count);
                font_outlines = r.ReadBytes(setup.fonts_count);
                if (dta_version >= 48) // 3.4.1
                {
                    for (int i = 0; i < setup.fonts_count; ++i)
                    {
                        Int32 font_offset_y = r.ReadInt32();
                        if (dta_version >= 49) // 3.4.1_2
                        {
                            Int32 font_linespacing = r.ReadInt32();
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < setup.fonts_count; ++i)
                {
                    Int32 flags       = r.ReadInt32();
                    Int32 sizePt      = r.ReadInt32();
                    Int32 outline     = r.ReadInt32();
                    Int32 yOffset     = r.ReadInt32();
                    Int32 lineSpacing = Math.Max(0, r.ReadInt32());
                }
            }

            // parse sprite flags
            Int32 sprites_count_max = 6000;

            if (dta_version >= 24) // pre 2.5.6
            {
                sprites_count_max = r.ReadInt32();
            }

            sprite_flags = r.ReadBytes(sprites_count_max);

            // parse inventory items info
            inventoryItems = new AGSInventoryItem[setup.inventory_items_count];
            AGSAlignedStream ar1 = new AGSAlignedStream(r);

            for (int i = 0; i < setup.inventory_items_count; ++i)
            {
                inventoryItems[i] = new AGSInventoryItem();
                inventoryItems[i].LoadFromStream(ar1);
                //NOTE(adm244): reset aligned stream??
            }

            // parse cursors info
            AGSAlignedStream ar2 = new AGSAlignedStream(r);

            cursors = new AGSCursorInfo[setup.cursors_count];
            for (int i = 0; i < cursors.Length; ++i)
            {
                cursors[i] = new AGSCursorInfo();
                cursors[i].LoadFromStream(ar2);
            }

            characters = new AGSCharacter[setup.characters_count];

            if (dta_version > 32) // 3.x
            {
                // parse characters interaction scripts
                for (int i = 0; i < characters.Length; ++i)
                {
                    characters[i] = new AGSCharacter();
                    characters[i].interactions.LoadFromStream(r);
                }

                // parse inventory items interaction scripts
                for (int i = 1; i < inventoryItems.Length; ++i)
                {
                    //inventoryItems[i] = new AGSInventoryItem();
                    inventoryItems[i].interactions.LoadFromStream(r);
                }
            }
            else // 2.72 and older
            {
                for (int i = 0; i < characters.Length; ++i)
                {
                    characters[i] = new AGSCharacter();
                    characters[i].interactions_old.LoadFromStream(r);
                }

                for (int i = 0; i < inventoryItems.Length; ++i)
                {
                    //inventoryItems[i] = new AGSInventoryItem();
                    inventoryItems[i].interactions_old.LoadFromStream(r);
                }

                Int32 globalvars_count = r.ReadInt32();
                globalvars = new AGSInteractionVariable[globalvars_count];
                for (int i = 0; i < globalvars.Length; ++i)
                {
                    globalvars[i] = new AGSInteractionVariable();
                    globalvars[i].LoadFromStream(r);
                }
            }

            // parse dictionary
            if (setup.load_dictionary != 0)
            {
                dictionary.LoadFromStream(r);
            }

            // parse global script
            globalScript.ReadFromStream(r);

            // parse dialog script
            if (dta_version > 37) // 3.1.0
            {
                dialogScript.ReadFromStream(r);
            }

            // parse other scripts
            if (dta_version >= 31) // 2.7.0
            {
                Int32 modules_count = r.ReadInt32();
                scriptModules = new AGSScript[modules_count];
                for (int i = 0; i < scriptModules.Length; ++i)
                {
                    scriptModules[i] = new AGSScript();
                    scriptModules[i].ReadFromStream(r);
                }
            }

            // parse views
            if (dta_version > 32) // 3.x
            {
                views = new AGSView[setup.views_count];
                for (int i = 0; i < views.Length; ++i)
                {
                    views[i] = new AGSView();
                    views[i].LoadFromStream(r);
                }
            }
            else // 2.7.2 and older
            {
                views272 = new AGSView272[setup.views_count];
                for (int i = 0; i < views272.Length; ++i)
                {
                    views272[i] = new AGSView272();
                    views272[i].LoadFromStream(r);
                }
            }

            // parse characters
            AGSAlignedStream ar3 = new AGSAlignedStream(r);

            for (int i = 0; i < characters.Length; ++i)
            {
                characters[i].LoadFromStream(ar3);
                ar.Reset();
            }

            if (dta_version >= 21) // 2.54
            {
                //TODO(adm244): real parsing
                r.BaseStream.Seek(20 * 50, SeekOrigin.Current);
            }

            ParseGlobalMessages(r, dta_version);

            ParseDialogs(r);

            if (dta_version <= 37) // 3.0 and older
            {
                for (int i = 0; i < dialogs.Length; ++i)
                {
                    dialogs[i].old_dialog_code = r.ReadBytes(dialogs[i].code_size);

                    Int32  scriptSize = r.ReadInt32();
                    byte[] encodedStr = r.ReadBytes(scriptSize);
                    dialogs[i].old_dialog_script = AGSEncryption.DecryptAvis(encodedStr);
                }

                if (dta_version <= 25) // 2.60 and older
                {
                    while (true)
                    {
                        uint mark = r.ReadUInt32();
                        r.BaseStream.Seek(-sizeof(UInt32), SeekOrigin.Current);

                        if (mark == GUI_SIGNATURE)
                        {
                            break;
                        }

                        string dialogString = r.ReadCString();
                        oldDialogStrings.Add(dialogString);
                    }
                }
                else
                {
                    while (true)
                    {
                        Int32 length = r.ReadInt32();
                        if ((UInt32)length == GUI_SIGNATURE)
                        {
                            r.BaseStream.Seek(-sizeof(UInt32), SeekOrigin.Current);
                            break;
                        }

                        byte[] encodedStr = r.ReadBytes(length);
                        oldDialogStrings.Add(AGSEncryption.DecryptAvis(encodedStr));
                    }
                }
            }

            int gui_version = ParseGUIs(r);

            ParseGUIControls(r, gui_version);

            if (dta_version >= 25) // 2.60+
            {
                ParsePlugins(r);

                ParseCustomProperties(r);
                ParseObjectsScriptNames(r, dta_version);
            }

            if (dta_version >= 41) // 3.2.0+
            {
                audioStorage = new AGSAudioStorage();
                audioStorage.LoadFromStream(r);
            }

            if (dta_version >= 36) // 2.8 ???
            {
                ParseRoomsDebugInfo(r);
            }
        }
        //TODO(adm244): parse fixups in AGSScript and convert them, so that we only pass here AGSScript and ip
        public static AGSInstruction DisassembleInstruction(AGSScript script, AGSFixupType[] fixups, int[] code, int ip)
        {
            AGSInstruction instruction = new AGSInstruction();

            byte  instanceId = (byte)((code[ip] >> 24) & 0xFF);
            Int32 opcodeRaw  = (Int32)(code[ip] & 0x00FFFFFF);

            Debug.Assert(Enum.IsDefined(typeof(AGSOpcodes), opcodeRaw));

            AGSOpcodes opcode = (AGSOpcodes)(opcodeRaw);

            for (int i = 0; i < Instructions.Length; ++i)
            {
                if (Instructions[i].Opcode == opcode)
                {
                    instruction.InstanceId = instanceId;
                    instruction.Opcode     = opcode;
                    instruction.Mnemonic   = Instructions[i].Mnemonic;

                    Debug.Assert((ip + Instructions[i].ArgumentsCount) < code.Length);

                    instruction.Arguments = new AGSArgument[Instructions[i].ArgumentsCount];
                    for (int arg = 0; arg < instruction.ArgumentsCount; ++arg)
                    {
                        int index = ip + arg + 1;
                        int value = code[index];

                        instruction.Arguments[arg].Type       = AGSArgumentType.None;
                        instruction.Arguments[arg].IntValue   = 0;
                        instruction.Arguments[arg].FloatValue = float.NaN;
                        instruction.Arguments[arg].Name       = string.Empty;

                        switch (Instructions[i].Arguments[arg])
                        {
                        //NOTE(adm244): integer literal can also store a float number
                        // e.g. movlit instruction can load floats as well as ints
                        case AGSBinaryArgumentType.IntLiteral:
                        {
                            AGSFixupType fixuptype = fixups[index];
                            //Debug.Assert(Enum.IsDefined(typeof(AGSArgumentType), type));

                            AGSArgumentType type = GetArgumentType(fixuptype, Instructions[i].Arguments[arg]);
                            instruction.Arguments[arg].Type = type;

                            switch (type)
                            {
                            case AGSArgumentType.IntConstant:
                            case AGSArgumentType.StackOffset:
                                //FIX(adm244): get actual stack value from StackOffset
                                instruction.Arguments[arg].IntValue = value;
                                break;

                            case AGSArgumentType.ImportsOffset:
                                instruction.Arguments[arg].Name = script.Imports[value];
                                break;

                            case AGSArgumentType.FunctionOffset:
                                int exportIndex = GetExportIndex(script, value);
                                instruction.Arguments[arg].Name = script.Exports[exportIndex].Name;
                                break;

                            case AGSArgumentType.StringsOffset:
                                int stringIndex = GetStringIndex(script, value);
                                instruction.Arguments[arg].Name = '"' + script.Strings[stringIndex] + '"';
                                break;

                            default:
                                Debug.Assert(false, "Unknown argument type!");
                                break;
                            }
                        }
                        break;

                        case AGSBinaryArgumentType.FloatLiteral:
                            instruction.Arguments[arg].Type       = AGSArgumentType.FloatConstant;
                            instruction.Arguments[arg].FloatValue = IEEE754Utils.Int32BitsToFloat(value);
                            break;

                        case AGSBinaryArgumentType.Register:
                            instruction.Arguments[arg].Type     = AGSArgumentType.RegisterIndex;
                            instruction.Arguments[arg].IntValue = value;
                            instruction.Arguments[arg].Name     = RegisterNames[value];
                            break;

                        default:
                            Debug.Assert(false, "Unknown binary argument type!");
                            break;
                        }

                        Debug.Assert(instruction.Arguments[arg].Type != AGSArgumentType.None);
                    }

                    break;
                }
            }

            //NOTE(adm244): swap arguments to match "mov <dest>, <src>" pattern
            if (instruction.Opcode == AGSOpcodes.REGTOREG)
            {
                Debug.Assert(instruction.ArgumentsCount == 2);

                AGSArgument temp = instruction.Arguments[0];
                instruction.Arguments[0] = instruction.Arguments[1];
                instruction.Arguments[1] = temp;
            }

            return(instruction);
        }
Esempio n. 6
0
 public void ReadSCOM3Block(BinaryReader reader, int roomVersion)
 {
     SCOM3 = new AGSScript();
     SCOM3.ReadFromStream(reader);
 }
Esempio n. 7
0
 public AGSRoomScript()
 {
     SCOM3      = new AGSScript();
     SourceCode = string.Empty;
 }