예제 #1
0
        private Script ReadScript(UInt32 offset, UInt32 nextoffset)
        {
            Script script;
            int    i;

            //go to first offset
            reader.BaseStream.Seek(offset, SeekOrigin.Begin);
            script = new Script();
            //read header
            script.Unknown       = reader.ReadUInt16();
            script.NbEntities    = reader.ReadByte();
            script.NbModels      = reader.ReadByte();
            script.StringOffset  = reader.ReadUInt16();
            script.NbAkaoOffsets = reader.ReadUInt16();
            script.Scale         = reader.ReadUInt16();
            for (i = 0; i < 3; i++)
            {
                script.Blank[i] = reader.ReadUInt16();
            }
            script.Creator = Encoding.Default.GetString(reader.ReadBytes(8));
            script.Name    = Encoding.Default.GetString(reader.ReadBytes(8));
            for (i = 0; i < script.NbEntities; i++)
            {
                script.Entities[i] = Encoding.Default.GetString(reader.ReadBytes(8));
            }
            //read offsets
            for (i = 0; i < script.NbAkaoOffsets; i++)
            {
                script.AkaoOffsets[i] = reader.ReadUInt32();
            }
            for (i = 0; i < script.NbEntities; i++)
            {
                for (int j = 0; j < 32; j++)
                {
                    script.EntityScripts[i, j] = Convert.ToUInt16(reader.ReadUInt16());
                }
            }
            //read scripts
            for (i = 0; i < script.NbEntities; i++)
            {
                for (int j = 0; j < 32; j++)
                {
                    byte         code;
                    EntityScript sc = new EntityScript();
                    Opcode       op;
                    reader.BaseStream.Seek((UInt32)script.EntityScripts[i, j] + offset, SeekOrigin.Begin);
                    do
                    {
                        code = reader.ReadByte();  // read opcode
                        op   = Opcodes.List[code]; // assign opcode from known list
                        byte   count = 0;
                        byte[] buff;
                        if (op.Operands != null)
                        {
                            while (count < (byte)op.Operands.Length)
                            {
                                Operand oper = op.Operands[count];
                                if (oper.Size < 8)
                                {
                                    //prepare BitVector sections
                                    int len    = 0;
                                    int secidx = 0;
                                    List <BitVector32.Section> sections = new List <BitVector32.Section>();
                                    while (oper.Size < 8 && len <= 32)
                                    {
                                        BitVector32.Section sec;
                                        if (secidx == 0)
                                        {
                                            sec = BitVector32.CreateSection((short)((1 << oper.Size) - 1));
                                        }
                                        else
                                        {
                                            sec = BitVector32.CreateSection((short)((1 << oper.Size) - 1), sections[secidx - 1]);
                                        }
                                        sections.Add(sec);
                                        len += oper.Size;
                                        secidx++;
                                        if ((count + secidx) >= op.Operands.Length)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            oper = op.Operands[count + secidx];
                                        }
                                    }
                                    //assign values from byte array
                                    buff = reader.ReadBytes((int)(len / 8));
                                    int valuetoparse = 0;
                                    for (int k = 0; k < buff.Length; k++)
                                    {
                                        valuetoparse += (buff[k] << (k * 8));
                                    }
                                    BitVector32 bv = new BitVector32(valuetoparse);
                                    for (int idx = 0; idx < secidx; idx++)
                                    {
                                        oper          = op.Operands[count];
                                        oper.Value    = new byte[1];
                                        oper.Value[0] = (byte)bv[sections[idx]];
                                        count++;
                                    }
                                }
                                else
                                {
                                    buff       = reader.ReadBytes((int)oper.Size / 8);
                                    oper.Value = buff;
                                    count++;
                                }
                            }
                        }
                        sc.Opcodes.Add(op);
                    } while (code != 0);
                    script.Scripts[i, j] = sc;
                }
            }

            //read dialogs
            reader.BaseStream.Seek((UInt32)script.StringOffset + offset, SeekOrigin.Begin);
            script.NbDialogs = reader.ReadUInt16();
            for (i = 0; i < script.NbDialogs; i++)
            {
                script.DialogOffsets[i] = Convert.ToUInt16(reader.ReadUInt16() + script.StringOffset);
            }
            for (i = 0; i < script.NbDialogs; i++)
            {
                byte[] dialog;
                int    size;
                if ((i + 1) < script.NbDialogs)
                {
                    size = script.DialogOffsets[i + 1] - script.DialogOffsets[i];
                }
                else
                {
                    UInt32 next = script.NbAkaoOffsets == 0 ? nextoffset : script.AkaoOffsets[0];
                    size = Convert.ToInt32(next - script.DialogOffsets[i]);
                }
                dialog = new byte[size];
                reader.BaseStream.Seek(script.DialogOffsets[i] + offset, SeekOrigin.Begin);
                dialog            = reader.ReadBytes(size);
                script.Dialogs[i] = FF7Text.DecodeBytes(dialog, size);
                dialog            = null;
            }

            //read akao
            for (i = 0; i < script.NbAkaoOffsets; i++)
            {
                AKAOFrame frm = new AKAOFrame();
                reader.BaseStream.Seek((UInt32)script.AkaoOffsets[i] + offset, SeekOrigin.Begin);
                frm.Magic       = Encoding.Default.GetString(reader.ReadBytes(4));
                frm.Id          = reader.ReadUInt16();
                frm.Length      = reader.ReadUInt16();
                frm.Unknown     = reader.ReadBytes(8);
                script.Akaos[i] = frm;
            }
            return(script);
        }