예제 #1
0
        public void NewType()
        {
            RSARPlayerInfoNode node = new RSARPlayerInfoNode();

            node.Name = _resource.FindName("NewPlayerInfo");
            RSARFolderNode folder = _resource as RSARFolderNode;
            RSARNode       rsar   = folder.RSARNode;

            if (rsar != null)
            {
                node._infoIndex = rsar._infoCache[2].Count;
                rsar._infoCache[2].Add(node);
            }
            _resource.AddChild(node);
        }
        public void NewSound()
        {
            RSARSoundNode node = new RSARSoundNode
            {
                Name = _resource.FindName("NewSound")
            };
            RSARFolderNode folder = _resource as RSARFolderNode;
            RSARNode       rsar   = folder.RSARNode;

            if (rsar != null)
            {
                node._infoIndex = rsar._infoCache[0].Count;
                rsar._infoCache[0].Add(node);
            }

            _resource.AddChild(node);
        }
예제 #3
0
 private static int EncodeMaskGroup(SYMBHeader *symb, SYMBMaskHeader *header, List <RSAREntryNode> gList, RSARNode n, int grp)
 {
     int[] stringIds = gList.Select(x => x._rebuildStringId).Where(x => x >= 0).ToArray();
     SYMBMaskEntry.Build(stringIds, symb, header, header->Entries);
     return(SYMBMaskHeader.Size + (stringIds.Length * 2 - 1) * SYMBMaskEntry.Size);
 }
예제 #4
0
        internal int EncodeFILEBlock(FILEHeader *header, VoidPtr baseAddress, RSAREntryList entries, RSARNode node)
        {
            int     len      = 0;
            VoidPtr baseAddr = (VoidPtr)header + 0x20;
            VoidPtr addr     = baseAddr;

            //Build files - order by groups
            foreach (RSARGroupNode g in entries._groups)
            {
                int             headerLen = 0, audioLen = 0;
                int             i = 0;
                INFOGroupEntry *e = (INFOGroupEntry *)((VoidPtr)g._headerAddr + INFOGroupHeader.Size + 4 + g._files.Count * 8);
                g._headerAddr->_headerOffset = (int)(addr - baseAddress);
                foreach (RSARFileNode f in g._files)
                {
                    e[i]._headerLength = f._headerLen;
                    e[i]._headerOffset = headerLen;

                    headerLen += f._headerLen;

                    ++i;
                }
                i = 0;
                VoidPtr wave = addr + headerLen;
                g._headerAddr->_waveDataOffset = (int)(wave - baseAddress);
                foreach (RSARFileNode f in g._files)
                {
                    f._rebuildAudioAddr = wave + audioLen;
                    f.Rebuild(addr, f._headerLen, true);

                    e[i]._dataOffset = f._audioLen == 0 ? 0 : audioLen;
                    e[i]._dataLength = f._audioLen;

                    addr     += f._headerLen;
                    audioLen += f._audioLen;

                    ++i;
                }

                addr += audioLen;
                g._headerAddr->_headerLength   = headerLen;
                g._headerAddr->_waveDataLength = audioLen;
            }

            len = ((int)addr - (int)(VoidPtr)header).Align(0x20);

            //Set header
            header->_header._tag    = FILEHeader.Tag;
            header->_header._length = len;

            return(len);
        }
예제 #5
0
        internal int EncodeINFOBlock(INFOHeader *header, RSAREntryList entries, RSARNode node)
        {
            int len = 0;

            VoidPtr    baseAddr = header->_collection.Address;
            ruint *    values   = (ruint *)baseAddr;
            VoidPtr    dataAddr = baseAddr + 0x30;
            RuintList *entryList;
            int        index = 0;

            //Set up sound ruint list
            values[0] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList *)dataAddr;
            entryList->_numEntries = entries._sounds.Count;
            dataAddr += entries._sounds.Count * 8 + 4;

            //Write sound entries
            foreach (RSAREntryNode r in entries._sounds)
            {
                r._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r.Rebuild(dataAddr, r._calcSize, true);
                dataAddr += r._calcSize;
            }
            index = 0;
            //Set up bank ruint list
            values[1] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList *)dataAddr;
            entryList->_numEntries = entries._banks.Count;
            dataAddr += entries._banks.Count * 8 + 4;

            //Write bank entries
            foreach (RSAREntryNode r in entries._banks)
            {
                r._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r.Rebuild(dataAddr, r._calcSize, true);
                dataAddr += r._calcSize;
            }
            index = 0;
            //Set up playerInfo ruint list
            values[2] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList *)dataAddr;
            entryList->_numEntries = entries._playerInfo.Count;
            dataAddr += entries._playerInfo.Count * 8 + 4;

            //Write playerInfo entries
            foreach (RSAREntryNode r in entries._playerInfo)
            {
                r._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r.Rebuild(dataAddr, r._calcSize, true);
                dataAddr += r._calcSize;
            }
            index = 0;
            //Set up file ruint list
            values[3] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList *)dataAddr;
            entryList->_numEntries = entries._files.Count;
            dataAddr += entries._files.Count * 8 + 4;

            //Write file entries
            foreach (RSARFileNode file in entries._files)
            {
                //if (file._groupRefs.Count == 0 && !(file is RSARExtFileNode))
                //    continue;

                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                INFOFileHeader *fileHdr = (INFOFileHeader *)dataAddr;
                dataAddr += INFOFileHeader.Size;
                RuintList *list = (RuintList *)dataAddr;
                fileHdr->_entryNumber = -1;
                if (file is RSARExtFileNode)
                {
                    uint extFileSize = 0;

                    //Make an attempt to get current file size
                    if (file.ExternalFileInfo.Exists)
                    {
                        extFileSize = (uint)file.ExternalFileInfo.Length;
                    }

                    if (file._extFileSize != extFileSize && extFileSize != 0)
                    {
                        file._extFileSize = extFileSize;
                    }

                    //Shouldn't matter if 0
                    fileHdr->_headerLen = file._extFileSize;

                    fileHdr->_dataLen      = 0;
                    fileHdr->_stringOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr);

                    sbyte *dPtr = (sbyte *)list;
                    file._extPath.Write(ref dPtr);
                    dataAddr += ((int)((VoidPtr)dPtr - (VoidPtr)dataAddr)).Align(4);

                    fileHdr->_listOffset = (uint)((VoidPtr)dataAddr - (VoidPtr)baseAddr);
                    dataAddr            += 4; //Empty list
                }
                else
                {
                    fileHdr->_headerLen = (uint)file._headerLen;
                    fileHdr->_dataLen   = (uint)file._audioLen;
                    //fileHdr->_stringOffset = 0;
                    fileHdr->_listOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr);
                    list->_numEntries    = file._groupRefs.Count;
                    INFOFileEntry *fileEntries = (INFOFileEntry *)((VoidPtr)list + 4 + file._groupRefs.Count * 8);
                    int            z           = 0;
                    List <int>     used        = new List <int>();
                    foreach (RSARGroupNode g in file._groupRefs)
                    {
                        list->Entries[z]        = (uint)((VoidPtr)(&fileEntries[z]) - baseAddr);
                        fileEntries[z]._groupId = g._rebuildIndex;
                        int[] all  = g._files.FindAllOccurences(file);
                        bool  done = false;
                        foreach (int i in all)
                        {
                            if (!used.Contains(i))
                            {
                                fileEntries[z]._index = i;
                                used.Add(i);
                                done = true;
                                break;
                            }
                        }
                        if (!done)
                        {
                            fileEntries[z]._index = g._files.IndexOf(file);
                        }
                        z++;
                    }
                    dataAddr = (VoidPtr)fileEntries + file._groupRefs.Count * INFOFileEntry.Size;
                }
            }
            index = 0;
            //Set up group ruint list
            values[4] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList *)dataAddr;
            entryList->_numEntries = entries._groups.Count;
            dataAddr += entries._groups.Count * 8 + 4;

            //Write group entries
            foreach (RSAREntryNode r in entries._groups)
            {
                r._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r.Rebuild(dataAddr, r._calcSize, true);
                dataAddr += r._calcSize;
            }

            //Write footer
            values[5] = (uint)dataAddr - (uint)baseAddr;
            *(INFOFooter *)dataAddr = node._ftr;

            //Set header
            header->_header._tag    = INFOHeader.Tag;
            header->_header._length = len = ((int)((dataAddr + INFOFooter.Size) - (baseAddr - 8))).Align(0x20);

            return(len);
        }
예제 #6
0
        internal int CalculateSize(RSAREntryList entries, RSARNode node)
        {
            //Header
            _headerLen = 0x40;

            //SYMB, INFO, FILE Headers
            _symbLen = 0x20;
            _infoLen = 0x8;
            _fileLen = 0x20;

            #region SYMB

            //String offsets
            _symbLen += entries._strings.Count * 4;

            //Strings are packed tightly with no trailing pad
            _symbLen += entries._stringLength;

            //Mask entries
            _symbLen += 32;                                    //Headers
            _symbLen += (entries._strings.Count * 2 - 4) * 20; //Entries

            //Align
            _symbLen = _symbLen.Align(0x20);

            #endregion

            #region Info

            //Info ruint collection and ruint list counts
            _infoLen += 0x30;

            int sounds = 4, playerInfo = 4, banks = 4, groups = 4, files = 4;

            //ruint sizes
            sounds     += entries._sounds.Count * 8;
            playerInfo += entries._playerInfo.Count * 8;
            groups     += entries._groups.Count * 8;
            banks      += entries._banks.Count * 8 + 8;
            files      += entries._files.Count * 8;

            //Evaluate entries with child offsets
            foreach (RSAREntryNode s in entries._sounds)
            {
                sounds += s.CalculateSize(true);
            }
            foreach (RSAREntryNode s in entries._playerInfo)
            {
                playerInfo += s.CalculateSize(true);
            }
            foreach (RSAREntryNode s in entries._banks)
            {
                banks += s.CalculateSize(true);
            }
            foreach (RSAREntryNode s in entries._groups)
            {
                groups += s.CalculateSize(true);
            }
            foreach (RSARFileNode s in entries._files)
            {
                if (s._groupRefs.Count == 0 && !(s is RSARExtFileNode))
                {
                    Console.WriteLine(s.Name);
                }

                files += INFOFileHeader.Size + 4 + (!(s is RSARExtFileNode) ?
                                                    (s._groupRefs.Count * (8 + INFOFileEntry.Size)) :
                                                    (s._extPath.Length + 1).Align(4));
            }

            //Footer and Align
            _infoLen = ((_infoLen += (sounds + banks + playerInfo + files + groups)) + 0x10).Align(0x20);

            #endregion

            #region File

            foreach (RSARGroupNode g in entries._groups)
            {
                foreach (RSARFileNode f in g._files)
                {
                    _fileLen += f.CalculateSize(true);
                }
            }

            //Align
            _fileLen = _fileLen.Align(0x20);

            #endregion

            return(_headerLen + _symbLen + _infoLen + _fileLen);
        }
예제 #7
0
        //Failed attempts at generating symb ids commented out below, enjoy

        //static void GenIds(SYMBHeader* symb, SYMBMaskHeader* header, int index, ushort allowedBit)
        //{
        //    SYMBMaskEntry* first = &header->Entries[index];
        //    string mainName = symb->GetStringEntry(first->_stringId);

        //    for (int i = 1; i < header->_numEntries; i += 2)
        //    {
        //        SYMBMaskEntry* secName = &header->Entries[i];
        //        SYMBMaskEntry* secBit = &header->Entries[i + 1];

        //        if (i == index || secBit->_bit != allowedBit)
        //            continue;

        //        string compName = symb->GetStringEntry(secName->_stringId);

        //        int bitIndex = mainName.CompareBits(compName);
        //        if (bitIndex >= 0)
        //        {
        //            //Set the bit index
        //            secBit->_bit = (ushort)bitIndex;

        //            int bit = bitIndex % 8;
        //            int byteIndex = (bitIndex - bit) / 8;

        //            bool leftFound = false, rightFound = false;

        //            mainName = compName;

        //            //Keeping looking down the list for the left and right entries
        //            for (int x = i + 2; x < header->_numEntries; x += 2)
        //            {
        //                SYMBMaskEntry* lrName = &header->Entries[x];
        //                SYMBMaskEntry* lrBit = &header->Entries[x + 1];
        //                compName = symb->GetStringEntry(lrName->_stringId);

        //                if (x == index || lrBit->_bit != allowedBit)
        //                    continue;

        //                bool forceLeft = false;

        //                if (byteIndex >= Math.Min(mainName.Length, compName.Length))
        //                    forceLeft = true;

        //                if (forceLeft || mainName.AtBit(bitIndex) != compName.AtBit(bitIndex))
        //                {
        //                    if (leftFound)
        //                        continue;

        //                    leftFound = true;

        //                    secBit->_leftId = x + 1;
        //                    GenIds(symb, header, x, lrBit->_bit);
        //                }
        //                else
        //                {
        //                    if (rightFound)
        //                        continue;

        //                    rightFound = true;

        //                    secBit->_rightId = x + 1;
        //                    GenIds(symb, header, x, lrBit->_bit);
        //                }
        //            }

        //            if (!leftFound) //No strings matched
        //                secBit->_leftId = i;
        //            else if (!rightFound) //All strings matched
        //                secBit->_rightId = i;

        //            break;
        //        }
        //    }
        //}

        //String Table to convert to a tree
        //string[] stringTable = new string[] { "SDPLAYER_BGM", "SDPLAYER_SE", "SDPLAYER_VOICE", "SDPLAYER_SYSTEM", "SDPLAYER_LOOP", "SDPLAYER_VOICE2", "SDPLAYER_SE_NOEFFECT" };

        //public class TEntry
        //{
        //    public string _string;
        //    public string _binary;
        //    public int _bit = -1;
        //    public int _leftID = -1;
        //    public int _rightID = -1;
        //    public int _stringID;
        //    public int _id;

        //    public TEntry(RSAREntryState s)
        //    {
        //        _binary = (_string = s._node._fullPath).ToBinaryArray();
        //        _stringID = s._stringId;
        //        _id = s._index;
        //    }
        //}

        //Making the output table to save me buttloads of time >.>
        //public void convertToBinary(string):
        //    ''' Converts a text string to a string representation of itself in binary. '''
        //    return ''.join(['%08d'%int(bin(ord(i))[2:]) for i in string])

        //Populating an empty table for my own convenience.
        //I assume the stringlist is ordered by ID, and is the first and only segment in the symb.
        //Cause I'm a lazy bastard.

        //Normal String, String (in binary), bit, LeftID, RightID, StringID, ID

        //outputTable = [{'string':stringTable[x], 'binary':convertToBinary(stringTable[x]),
        //                'bit':-1, 'LeftID':-1, 'RightID':-1, 'StringID':x, 'ID':x} for x in xrange(len(stringTable))]

        //private static void WriteData(List<TEntry> Left, List<TEntry> Right, int bit)
        //{
        //    //Writes all the necessary information to the node

        //    TEntry currentNode = Right[0];

        //    //Write Position
        //    currentNode._bit = bit;

        //    //Write the left branch (matching) This is a bit fugly, because of how I handle the output table.
        //    //I basically determine the 'line' based off the ID.
        //    if (Left.Count > 1)
        //        currentNode._leftID = Left[0]._id * 2;
        //    else
        //    {
        //        currentNode._leftID = Left[0]._id * 2 - 1;
        //        //Edge case for the first node, who has no -1 line.
        //        if (currentNode._leftID < 0)
        //            currentNode._leftID = 0;
        //    }

        //    if (Right.Count > 1)
        //        currentNode._rightID = Right[1]._id * 2;
        //    else
        //    {
        //        currentNode._rightID = Right[0]._id * 2 - 1;
        //        //Edge case for the first node, who has no -1 line.
        //        if (currentNode._rightID < 0)
        //            currentNode._rightID = 0;
        //    }
        //}

        //private static void SplitTable(List<TEntry> outputTable, out List<TEntry> Left, out List<TEntry> Right)
        //{
        //    //Splits the table in two and writes the data

        //    TEntry originalNode = outputTable[0];
        //    List<TEntry> Temp;

        //    //Iterate bit by bit
        //    int bit = 0, entry = 0;
        //    for (bit = 0; bit < originalNode._binary.Length; bit++)
        //    {
        //        char compareBit = originalNode._binary[bit];

        //        //Go over the table
        //        for (entry = 0; entry < outputTable.Count; entry++)
        //        {
        //            //F*****g Ugly edge case - initial string is too long to compare
        //            if (bit >= outputTable[entry]._binary.Length)
        //            {
        //                //Python stuff to change the 'start' of the table to the current position
        //                Temp = outputTable.ShiftFirst(entry);

        //                //Split the ordered table there into Left (matching) and right (non-matching)
        //                Left = new List<TEntry> { outputTable[entry] };

        //                Right = new List<TEntry>();
        //                foreach (TEntry t in Temp)
        //                    if (t._id != outputTable[entry]._id)
        //                        Right.Add(t);

        //                WriteData(Left, Right, bit);

        //                //It splits!
        //                return;
        //            }

        //            //This is the normal case - applies 90% of the time, I find.
        //            if (outputTable[entry]._binary[bit] != compareBit)
        //            {
        //                //Python stuff to change the 'start' of the table to the current position
        //                Temp = outputTable.ShiftFirst(entry);

        //                //Split the ordered table there into Left (matching) and right (non-matching)
        //                Left = new List<TEntry>();
        //                foreach (TEntry t in Temp)
        //                    if (t._binary[bit] == '0')
        //                        Left.Add(t);

        //                Right = new List<TEntry>();
        //                foreach (TEntry t in Temp)
        //                    if (t._binary[bit] == '1')
        //                        Right.Add(t);

        //                WriteData(Left, Right, bit);

        //                //It splits!
        //                return;
        //            }
        //        }
        //    }

        //    //If it got this far, then it ran out of bits.
        //    //So now we gotta

        //    //Split the ordered table there into Left (matching) and right (non-matching)
        //    Left = new List<TEntry> { originalNode };
        //    Right = new List<TEntry>();
        //    foreach (TEntry t in outputTable)
        //        if (t._id != originalNode._id)
        //            Right.Add(t);

        //    WriteData(Left, Right, bit);

        //    //It splits!
        //    return;
        //}

        //public static void CalcMatch(List<TEntry> outputTable)
        //{
        //    //Split the Table by node
        //    List<TEntry> Left, Right;
        //    SplitTable(outputTable, out Left, out Right);

        //    //foreach (TEntry t in Left)
        //    //    Console.WriteLine(String.Format("Left: {0} {1} {2} {3} ", t._string, t._bit, t._leftID, t._rightID));

        //    //Console.WriteLine("-------------------------------------------------");

        //    //foreach (TEntry t in Right)
        //    //    Console.WriteLine(String.Format("Right: {0} {1} {2} {3} ", t._string, t._bit, t._leftID, t._rightID));

        //    if (Left.Count > 1)
        //        CalcMatch(Left);
        //    if (Right.Count > 1)
        //        CalcMatch(Right);
        //}

        //public class PatriciaTree
        //{
        //    public string[] strings;
        //    public string[] bin_strings;
        //    public int out_node_idx = 0;

        //    public PatriciaTree(string[] str)
        //    {
        //        strings = str;
        //        bin_strings = strings.Select(x => x.ToBinaryArray()).ToArray();
        //    }

        //    public int[] partition_tree(List<int> idx_list, int position)
        //    {
        //        List<int> left = new List<int>(), right = new List<int>();
        //        for (int i = 0; i < idx_list.Count; i++ )
        //        {
        //            string bstr = bin_strings[i];
        //            if (position >= bstr.Length || position < 0)
        //                left.Add(i);
        //            else
        //            {
        //                char ch = bstr[position];
        //                if (ch == '1')
        //                    right.Add(i);
        //                else
        //                    left.Add(i);
        //            }
        //        }
        //        int total = left.Count + right.Count;
        //        if (total == 1)
        //        {
        //            //This is a leaf, woo

        //            int pos = -1, t;

        //            if (left.Count > 0)
        //                t = left[0];
        //            else
        //                t = right[0];

        //            return new int[] { pos, t };
        //        }
        //        else if (left.Count == 0 || right.Count == 0)
        //            //This is not a branch, let's try the next bit
        //            if (left.Count > 0)
        //                return partition_tree(left, position + 1);
        //            else
        //                return partition_tree(right, position + 1);
        //        else
        //        {
        //            int[] l = partition_tree(left, position + 1);
        //            int[] r = partition_tree(right, position + 1);
        //            return new int[] { position }.Append(l).Append(r);
        //        }
        //    }
        //    public int tree_size(int[] node)
        //    {
        //        //Node is the return from partition_tree()
        //        if (node[0] == -1)
        //            return 1;
        //        else
        //            return 1 + tree_size(new int[] { node[1] }) + tree_size(new int[] { node[2] });
        //    }
        //    public void dump_tree(int[] tree)
        //    {
        //        out_node_idx = 0;
        //        _dump_node(tree);
        //    }
        //    public void _dump_node(int[] node)
        //    {
        //        //Node is the return from partition_tree()
        //        int bit_id = node[0];
        //        if (bit_id == -1)
        //        {
        //            //We're packing a leaf
        //            Console.WriteLine(String.Format("{0} leaf  : {1}", out_node_idx, strings[node[1]]));
        //            out_node_idx += 1;
        //        }
        //        else
        //        {
        //            //We're packing a branch
        //            int left_size = tree_size(new int[] { node[1] });
        //            int left_idx = out_node_idx + 1;
        //            int right_idx = left_idx + left_size;
        //            Console.WriteLine(String.Format("{0} branch: bit={1} left={2} right={3}", out_node_idx, bit_id, left_idx, right_idx));
        //            out_node_idx += 1;
        //            dump_tree(new int[] { node[1] });
        //            dump_tree(new int[] { node[2] });
        //        }
        //    }
        //}

        //tree = PatriciaTree(('BANK_HOMEBUTTON','BANK_SYSTEM_SE','BANK_BGM','BANK_SOFTWARE_KEYBOARD_SE'))
        //print(tree.partition_tree())
        //tree.dump_tree(tree.partition_tree())

        private static int EncodeMaskGroup(SYMBHeader *symb, SYMBMaskHeader *header, List <RSAREntryState> group, RSARNode n, int grp)
        {
            SYMBMaskEntry *entry = header->Entries;
            //List<TEntry> outputTable = new List<TEntry>();

            int i = 0;

            foreach (RSAREntryState s in group)
            {
                entry[i++] = new SYMBMaskEntry(1, -1, -1, -1, s._stringId, s._index);
                if (s._index != 0)
                {
                    //entry[i++] = new SYMBMaskEntry(0, 0, 0, 0, -1, -1);
                    entry[i] = n._symbCache[grp][i++];
                }
                //outputTable.Add(new TEntry(s));
            }

            header->_numEntries = group.Count * 2 - 1;
            header->_rootId     = n._rootIds[grp];

            //GenIds(symb, header, 0, 0);
            //CalcMatch(outputTable);

            //foreach (TEntry t in outputTable)
            //{
            //    *entry++ = new SYMBMaskEntry(1, -1, -1, -1, t._stringID, t._id);
            //    if (t._id != 0)
            //        *entry++ = new SYMBMaskEntry(0, (short)t._bit, t._leftID, t._rightID, -1, -1);
            //}

            //PatriciaTree t = new PatriciaTree(group.Select(x => x._node._fullPath).ToArray());
            //int[] p = t.partition_tree(new List<int>(t.strings.Length), 0);
            //t.dump_tree(p);

            int len = 8 + i * SYMBMaskEntry.Size;

            //int rootId = 0;
            //int lowestBit = int.MaxValue;
            //entry = header->Entries;
            //for (int i = 2; i < header->_numEntries; i += 2)
            //{
            //    if (entry[i]._bit < lowestBit)
            //    {
            //        lowestBit = entry[i]._bit;
            //        rootId = i;
            //    }
            //}
            //header->_rootId = rootId;

            return(len);
        }
예제 #8
0
        public void RunEvent(int eventIndex)
        {
            //Get the current event and its id
            e = this[eventIndex];

            //Run event only if allowed or if an exception
            if (e == null || !_runEvents && !_runExceptions.Contains(eventId >> 16))
            {
                return;
            }

            uint eventIdTemp = eventId & 0xFFFFFF00; //Cut out unk value
            //if (_events.ContainsKey(eventIdTemp))
            //    _events[eventIdTemp].Invoke(this, null);

            //Variables that are used often
            int                 id;
            Script              script;
            Event               ev;
            int                 index;
            ArticleInfo         articleInfo;
            HitBox              hitbox;
            RequirementInfo     reqInfo;
            ActionChangeInfo    aChangeInfo;
            SubActionChangeInfo sChangeInfo;

            //Code what to do for each event here!
            switch (eventIdTemp)
            {
            case 0x01000000:     //Loop Rest 1 for Goto
                Application.DoEvents();
                break;

            case 0x00010100:     //Synchronous Timer
                _waitFrames = (int)(e[0].RealValue + 0.5f);
                break;

            case 0x00020000:     //No Operation
                break;

            case 0x00020100:     //Asynchronous Timer
                _waitFrames = Math.Max((int)(e[0].RealValue + 0.5f) - _frameIndex, 0);
                break;

            case 0x00040100:     //Set loop data
                _loopCount      = e[0];
                _loopStartIndex = e.Index + 1;
                _runEvents      = false;
                break;

            case 0x00050000:     //Start looping
                _looping      = true;
                _loopEndIndex = e.Index;
                _eventIndex   = _loopStartIndex;
                _runEvents    = true;
                break;

            case 0x000A0100:     //If
            case 0x000A0200:     //If Value
            case 0x000A0300:     //If Unk
            case 0x000A0400:     //If Comparison
                if (_runEvents)
                {
                    _currentIf = _ifIndex++;
                    _runEvents = false;
                    _ifInfo    = new IfInfo();

                    index = eventIndex + 1;
                    while (true)
                    {
                        if (index < Count)
                        {
                            ev = this[index];
                            id = (int)ev.EventID;
                            if (id == 0x000B0100 ||
                                id == 0x000B0200 ||
                                id == 0x000B0300 ||
                                id == 0x000B0400)
                            {
                                index++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    _ifInfo._reqIndices = new List <int>();
                    _ifInfo._reqIndices.Add(index);

                    _ifEndIndices.Add(0);
                    reqInfo = new RequirementInfo(e[0]);
                    for (int i = 1; i < ((eventId >> 8) & 0xFF); i++)
                    {
                        reqInfo._values.Add(e[i]);
                    }
                    _ifInfo._requirements = new List <List <RequirementInfo> >();
                    _ifInfo._requirements.Add(new List <RequirementInfo>());
                    _ifInfo._requirements[0].Add(reqInfo);
                }
                else
                {
                    _ifIndex++;
                }
                break;

            case 0x000E0000:     //Else
                if (!_runEvents)
                {
                    if (_ifIndex == _currentIf)
                    {
                        _ifInfo._elseIndex = eventIndex;
                    }
                }
                else
                {
                    if (_ifIndex == _currentIf + 1)
                    {
                        _eventIndex = _ifInfo._endIndex;
                    }
                }
                break;

            case 0x000D0100:     //Else If (req)
            case 0x000D0200:     //Else If Value (req val)
            case 0x000D0300:     //Else If Unk (req val unk)
            case 0x000D0400:     //Else If Comparison (req var val var)

                if (!_runEvents)
                {
                    if (_ifIndex == _currentIf)
                    {
                        index = eventIndex + 1;
                        while (true)
                        {
                            if (index < Count)
                            {
                                ev = this[index];
                                id = (int)ev.EventID;
                                if (id == 0x000B0100 ||
                                    id == 0x000B0200 ||
                                    id == 0x000B0300 ||
                                    id == 0x000B0400)
                                {
                                    index++;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        _ifInfo._reqIndices.Add(index);
                    }
                }
                else
                {
                    if (_ifIndex == _currentIf + 1)
                    {
                        _eventIndex = _ifInfo._endIndex;
                    }
                }

                if (!_runEvents && _ifIndex == _currentIf + 1)
                {
                    reqInfo = new RequirementInfo(e[0]);
                    for (int i = 1; i < eCount; i++)
                    {
                        reqInfo._values.Add(e[i]);
                    }
                    _ifInfo._requirements.Add(new List <RequirementInfo>());
                    _ifInfo._requirements[0].Add(reqInfo);
                }
                break;

            case 0x000B0100:     //And If
            case 0x000B0200:     //And If Value
            case 0x000B0300:     //And If Unk
            case 0x000B0400:     //And If Comparison
                if (!_runEvents && _ifIndex == _currentIf + 1)
                {
                    reqInfo = new RequirementInfo(e[0]);
                    for (int i = 1; i < eCount; i++)
                    {
                        reqInfo._values.Add(e[i]);
                    }
                    _ifInfo._requirements.Add(new List <RequirementInfo>());
                    _ifInfo._requirements[0].Add(reqInfo);
                }
                break;

            case 0x000F0000:     //End if
                _ifIndex--;
                if (!_runEvents)
                {
                    if (_ifIndex == _currentIf)
                    {
                        _ifInfo._endIndex = _ifEndIndices[_currentIf] = eventIndex + 1;
                        _eventIndex       = _ifInfo.Run();
                        _runEvents        = true;
                    }
                }
                break;

            case 0x00100200:     //Switch
                _cases       = new List <Parameter>();
                _caseIndices = new List <int>();

                //Turn off events to examine them until end switch
                //Then the examined data will be evaluated
                _runEvents = false;

                _switchStartIndex = eventIndex;
                break;

            case 0x00110100:     //Case
                if (!_runEvents)
                {
                    if (_cases != null && _caseIndices != null)
                    {
                        _cases.Add(e[0]);
                        _caseIndices.Add(e.Index);
                    }
                }
                else
                {
                    _eventIndex     = _switchEndIndex + 1;
                    _switchEndIndex = -1;
                }
                break;

            case 0x00120000:     //Default Case
                _defaultCaseIndex = e.Index;
                break;

            case 0x00130000:     //End Switch
                _runEvents      = true;
                _switchEndIndex = e.Index;

                //Apply cases
                index = 0;
                if (_switchStartIndex >= 0 && _switchStartIndex < Count)
                {
                    Parameter Switch = this[_switchStartIndex][1];
                    foreach (Parameter param in _cases)
                    {
                        if (Switch.Compare(param, 2))
                        {
                            _eventIndex = _caseIndices[index] + 1;
                            break;
                        }
                        index++;
                    }
                }

                if (_cases != null && index == _cases.Count && _defaultCaseIndex != -1)
                {
                    _eventIndex = _defaultCaseIndex + 1;
                }

                _defaultCaseIndex = -1;
                _switchStartIndex = -1;
                _cases            = null;

                break;

            case 0x00180000:     //Break
                _eventIndex     = _switchEndIndex + 1;
                _switchEndIndex = -1;
                break;

            case 0x10050200:     //Article Visiblity
                id = e[0];
                if (id < 0 || id >= RunTime._articles.Length)
                {
                    break;
                }
                articleInfo = RunTime._articles[id];
                if (articleInfo != null && articleInfo._model != null)
                {
                    articleInfo._model.IsRendering = e[1] != 0;
                }
                break;

            case 0x01010000:     //Loop Rest
                _waitFrames = 1;
                break;

            case 0x06000D00:     //Offensive Collison
            case 0x062B0D00:     //Thrown Collision
                hitbox            = new HitBox(e, Article != null ? Article.Index : -1);
                hitbox.HitboxID   = (int)(e[0] & 0xFFFF);
                hitbox.HitboxSize = e[5];
                RunTime._hitBoxes.Add(hitbox);
                break;

            case 0x06050100:     //Body Collision
                _hurtBoxType = e[0];
                break;

            case 0x06080200:     //Bone Collision
                id = e[0];
                if (Root.Model != null && Root.Model._linker.BoneCache.Length > id && id >= 0)
                {
                    MDL0BoneNode bone = Root.Model._linker.BoneCache[id] as MDL0BoneNode;
                    switch ((int)e[1])
                    {
                    case 0:
                        bone._nodeColor = Color.Transparent;
                        bone._boneColor = Color.Transparent;
                        break;

                    case 1:
                        bone._nodeColor = bone._boneColor = Color.FromArgb(255, 255, 0);
                        break;

                    default:
                        bone._nodeColor = bone._boneColor = Color.FromArgb(0, 0, 255);
                        break;
                    }
                    _boneCollisions.Add(bone);
                }
                break;

            case 0x06060100:     //Undo Bone Collision
                foreach (MDL0BoneNode bone in _boneCollisions)
                {
                    bone._nodeColor = bone._boneColor = Color.Transparent;
                }
                _boneCollisions = new List <MDL0BoneNode>();
                break;

            case 0x060A0800:     //Catch Collision 1
            case 0x060A0900:     //Catch Collision 2
            case 0x060A0A00:     //Catch Collision 3
                hitbox            = new HitBox(e, Article != null ? Article.Index : -1);
                hitbox.HitboxID   = e[0];
                hitbox.HitboxSize = e[2];
                RunTime._hitBoxes.Add(hitbox);
                break;

            case 0x060D0000:     //Terminate Catch Collisions
                for (int i = 0; i < RunTime._hitBoxes.Count; i++)
                {
                    if (RunTime._hitBoxes[i].IsCatch())
                    {
                        RunTime._hitBoxes.RemoveAt(i--);
                    }
                }
                break;

            case 0x00060000:     //Loop break
                _looping    = false;
                _eventIndex = _loopEndIndex + 1;
                _loopTime   = 0;
                break;

            case 0x06150F00:     //Special Offensive Collison
                hitbox            = new HitBox(e, Article != null ? Article.Index : -1);
                hitbox.HitboxID   = (int)(e[0] & 0xFFFF);
                hitbox.HitboxSize = e[5];
                RunTime._hitBoxes.Add(hitbox);
                break;

            case 0x06040000:     //Terminate Collisions
                for (int i = 0; i < RunTime._hitBoxes.Count; i++)
                {
                    if (RunTime._hitBoxes[i].IsOffensive(true))
                    {
                        RunTime._hitBoxes.RemoveAt(i--);
                    }
                }
                break;

            case 0x06030100:     //Delete hitbox
                for (int i = 0; i < RunTime._hitBoxes.Count; i++)
                {
                    HitBox hbox = RunTime._hitBoxes[i];
                    if (hbox.HitboxID == e[0] && hbox.IsOffensive(true))
                    {
                        RunTime._hitBoxes.RemoveAt(i--);
                        break;
                    }
                }
                break;

            case 0x060C0100:     //Delete Catch Collision
                for (int i = 0; i < RunTime._hitBoxes.Count; i++)
                {
                    HitBox hbox = RunTime._hitBoxes[i];
                    if (hbox.HitboxID == e[0] && hbox.IsCatch())
                    {
                        RunTime._hitBoxes.RemoveAt(i--);
                        break;
                    }
                }
                break;

            case 0x061B0500:     //Move hitbox
                foreach (HitBox hbox in RunTime._hitBoxes)
                {
                    if (hbox.HitboxID == e[0] && hbox.IsOffensive(true))
                    {
                        hbox._parameters[1] = e[1];
                        hbox._parameters[6] = e[2];
                        hbox._parameters[7] = e[3];
                        hbox._parameters[8] = e[4];
                        break;
                    }
                }
                break;

            case 0x04060100:     //Set animation frame
                //if (Article == null)
                //    RunTime.SetFrame((int)(e[0].RealValue + 0.05f));
                //else
                //    RunTime._articles[Article.Index].SetFrame((int)(e[0].RealValue + 0.05f));
                break;

            case 0x00070100:     //Subroutine
                script = (e[0] as EventOffset)._script;
                if (script != null && script != _script)
                {
                    script.Reset();
                    RunTime._runningScripts.Add(script);
                    script.SetFrame(0);
                }
                break;

            case 0x00080000:     //Return
                _return     = true;
                _eventIndex = Count;
                if (RunTime._runningScripts.Contains(_script))
                {
                    RunTime._runningScripts.Remove(_script);
                }
                break;

            case 0x00090100:     //Go to
                script = (e[0] as EventOffset)._script;
                if (script != null && script != _script)
                {
                    RunTime._runningScripts.Remove(_script);
                    script.Reset();
                    RunTime._runningScripts.Add(script);
                    script.SetFrame(0);
                }
                break;

            case 0x0A030100:     //Stop sound
                id = e[0];
                if (RunTime._playingSounds.ContainsKey(id))
                {
                    List <AudioInfo> aList = RunTime._playingSounds[id];
                    foreach (AudioInfo aInfo in aList)
                    {
                        if (aInfo._buffer != null)
                        {
                            aInfo._buffer.Stop();
                            aInfo._buffer.Dispose();
                            aInfo._stream.Dispose();
                        }
                    }
                    RunTime._playingSounds.Remove(id);
                }
                break;

            case 0x0A000100:     //Play sound
            case 0x0A010100:
            case 0x0A020100:
            case 0x0A040100:
            case 0x0A050100:
            case 0x0A060100:
            case 0x0A070100:
            case 0x0A080100:
            case 0x0A090100:
            case 0x0A0A0100:
            case 0x0A0B0100:
            case 0x0A0C0100:
            case 0x0A0D0100:
            case 0x0A0E0100:
            case 0x0A0F0100:

                if (RunTime._muteSFX)
                {
                    break;
                }

                if (Manager.SoundArchive != null)
                {
                    RSARNode             node   = Manager.SoundArchive;
                    List <RSAREntryNode> sounds = node._infoCache[0];

                    id = e[0];
                    if (sounds != null && id >= 0 && id < sounds.Count)
                    {
                        RSARSoundNode s = sounds[id] as RSARSoundNode;
                        if (s != null)
                        {
                            IAudioStream stream = s.CreateStreams()[0];
                            AudioBuffer  b      = Manager._audioProvider.CreateBuffer(stream);
                            AudioInfo    info   = new AudioInfo(b, stream);

                            if (RunTime._playingSounds.ContainsKey(id))
                            {
                                RunTime._playingSounds[id].Add(info);
                            }
                            else
                            {
                                RunTime._playingSounds[id] = new List <AudioInfo>()
                                {
                                    info
                                }
                            };

                            b.Reset();
                            b.Seek(0);
                            b.Play();
                        }
                    }
                }
                break;

            case 0x0B000200:     //Model Changer 1
            case 0x0B010200:     //Model Changer 2

                ModelVisibility visNode = null;
                if (Article != null)
                {
                    //Check if we have data to work with
                    articleInfo = RunTime._articles[Article.Index];

                    if (articleInfo == null ||
                        articleInfo._model == null ||
                        articleInfo._model._objList == null ||
                        articleInfo._article._mdlVis == null ||
                        articleInfo._article._mdlVis.Count == 0)
                    {
                        break;
                    }

                    visNode = articleInfo._article._mdlVis;
                }
                else
                {
                    //Check if we have data to work with
                    if (Root.Model == null ||
                        Root.Model._objList == null ||
                        Root.Data._modelVis.Count == 0)
                    {
                        break;
                    }

                    visNode = Root.Data._modelVis;
                }
                if (visNode != null)
                {
                    int refId    = ((int)((eventId >> 16) & 0xFF));
                    int switchId = e[0];
                    int groupId  = e[1];
                    visNode.ApplyVisibility(refId, switchId, groupId);
                }
                break;

            case 0x0B020100:     //Model visibility
                if (Article == null)
                {
                    Root.Model.IsRendering = e[0] != 0;
                }
                else if (Article.Index < RunTime._articles.Length && RunTime._articles[Article.Index]._model != null)
                {
                    RunTime._articles[Article.Index]._model.IsRendering = e[0] != 0;
                }
                break;

            case 0x0D000200:     //Concurrent Infinite Loop
                index = e[0];
                EventOffset off = (e[1] as EventOffset);
                if (off._script != null)
                {
                    if (RunTime._concurrentLoopScripts.ContainsKey(index))
                    {
                        RunTime._concurrentLoopScripts.Remove(index);
                    }
                    RunTime._concurrentLoopScripts.Add(index, off._script);
                }
                break;

            case 0x0D010100:     //Terminate Concurrent Infinite Loop
                index = e[0];
                if (RunTime._concurrentLoopScripts.ContainsKey(index))
                {
                    RunTime._concurrentLoopScripts.Remove(index);
                }
                break;

            case 0x0E000100:     //Set Air/Ground
                RunTime._location = (RunTime.Location)((int)e[0]);
                break;

            case 0x10000100:     //Generate Article
            case 0x10000200:     //Generate Article
            case 0x10030100:     //Remove Article

                //These events do a similar job!
                bool removeArticle = eID == 3;

                //Make sure we have all the data we need available
                MainControl main  = MainForm.Instance._mainControl;
                MovesetNode mNode = Manager.Moveset;
                if (mNode == null)
                {
                    break;
                }
                DataSection d = mNode.Data;
                if (d == null)
                {
                    break;
                }

                //Get the id of the article to be called and check it
                int aId2 = e[0];
                if (aId2 < 0 || aId2 >= RunTime._articles.Length)
                {
                    break;
                }

                //Get the called article from the article list
                articleInfo = RunTime._articles[aId2];

                if (articleInfo == null)
                {
                    return;
                }

                articleInfo.Running = !removeArticle;

                break;

            case 0x10040200:     //Set Anchored Article SubAction
            case 0x10070200:     //Set Remote Article SubAction
                id = e[0];
                int sId = e[1];
                if (id < 0 || id >= RunTime._articles.Length)
                {
                    break;
                }

                //Get the called article from the article list
                articleInfo = RunTime._articles[id];
                if (articleInfo != null)
                {
                    articleInfo.SubactionIndex = sId;
                    articleInfo._setAt         = _frameIndex;
                }
                break;

            case 0x10010200:     //Set Ex-Anchored Article Action
                break;

            case 0x12000200:     //Basic Var Set
            case 0x12060200:     //Float Var Set
                e[1].RealValue = e[0].RealValue;
                break;

            case 0x12010200:     //Basic Var Add
            case 0x12070200:     //Float Var Add
                e[1].RealValue = e[1].RealValue + e[0].RealValue;
                break;

            case 0x12020200:     //Basic Var Sub
            case 0x12080200:     //Float Var Sub
                e[1].RealValue = e[1].RealValue - e[0].RealValue;
                break;

            case 0x12030100:     //Basic Var Inc
                e[0].RealValue = e[0].RealValue + 1.0f;
                break;

            case 0x12040100:     //Basic Var Dec
                e[0].RealValue = e[0].RealValue - 1.0f;
                break;

            case 0x120A0100:     //Bit Variable Set
                e[0].RealValue = 1.0f;
                break;

            case 0x120B0100:     //Bit Variable Clear
                e[0].RealValue = 0.0f;
                break;

            case 0x120F0200:     //Float Variable Multiply
                e[1].RealValue = e[1].RealValue * e[0].RealValue;
                break;

            case 0x12100200:     //Float Variable Divide
                if (e[0].RealValue != 0)
                {
                    e[1].RealValue = e[1].RealValue / e[0].RealValue;
                }
                break;

            case 0x64000000:     //Allow Interrupt
                RunTime._allowInterrupt = true;
                break;

            case 0x02000300:     //Change Action Status
            case 0x02000400:
            case 0x02000500:
            case 0x02000600:

                break;

            case 0x02010200:     //Change Action
            case 0x02010300:
            case 0x02010400:
            case 0x02010500:
                aChangeInfo = new ActionChangeInfo(e[0]);
                reqInfo     = new RequirementInfo(e[1]);
                for (int i = 2; i < Count; i++)
                {
                    reqInfo._values.Add(e[i]);
                }
                aChangeInfo._requirements.Add(reqInfo);
                RunTime.AddActionChangeInfo(aChangeInfo);
                break;

            case 0x02040100:     //Additional Change Action Requirement
            case 0x02040200:
            case 0x02040300:
            case 0x02040400:

                break;

            case 0x02060100:     //Enable Action Status ID
                break;

            case 0x02080100:     //Disable Action Status ID
                break;

            case 0x02090200:     //Invert Action Status ID
                break;

            case 0x020A0100:     //Allow Specific Interrupt
                break;

            case 0x020B0100:     //Disallow Specific Interrupt
                break;

            case 0x020C0100:     //Unregister Interrupt
                break;

            case 0x04000100:     //Change Subaction
            case 0x04000200:
                sChangeInfo = new SubActionChangeInfo(e[0], eCount == 2 && e[1] != 0);
                RunTime.AddSubActionChangeInfo(sChangeInfo);
                break;

            case 0x04010200:     //Change Subaction
                sChangeInfo = new SubActionChangeInfo(e[0], false);
                sChangeInfo._requirements.Add(new RequirementInfo(e[1]));
                RunTime.AddSubActionChangeInfo(sChangeInfo);
                break;

            case 0x11010A00:     //External Graphic Effect
            case 0x11001000:     //Same as prev but with random offset and rotation
                bool random = ((eventId >> 16) & 0xFF) == 0;

                break;

            case 0x111A1000:     //Graphic Effect; no file

                break;
            }
        }
예제 #9
0
        internal int EncodeINFOBlock(INFOHeader* header, RSAREntryList entries, RSARNode node)
        {
            int len = 0;

            VoidPtr baseAddr = header->_collection.Address;
            ruint* values = (ruint*)baseAddr;
            VoidPtr dataAddr = baseAddr + 0x30;
            RuintList* entryList;
            int index = 0;

            //Set up sound ruint list
            values[0] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList*)dataAddr;
            entryList->_numEntries = entries._sounds.Count;
            dataAddr += entries._sounds.Count * 8 + 4;

            //Write sound entries
            foreach (RSAREntryState r in entries._sounds)
            {
                r._node._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r._node.Rebuild(dataAddr, r._node._calcSize, true);
                dataAddr += r._node._calcSize;
            }
            index = 0;
            //Set up bank ruint list
            values[1] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList*)dataAddr;
            entryList->_numEntries = entries._banks.Count;
            dataAddr += entries._banks.Count * 8 + 4;

            //Write bank entries
            foreach (RSAREntryState r in entries._banks)
            {
                r._node._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r._node.Rebuild(dataAddr, r._node._calcSize, true);
                dataAddr += r._node._calcSize;
            }
            index = 0;
            //Set up playerInfo ruint list
            values[2] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList*)dataAddr;
            entryList->_numEntries = entries._playerInfo.Count;
            dataAddr += entries._playerInfo.Count * 8 + 4;

            //Write playerInfo entries
            foreach (RSAREntryState r in entries._playerInfo)
            {
                r._node._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r._node.Rebuild(dataAddr, r._node._calcSize, true);
                dataAddr += r._node._calcSize;
            }
            index = 0;
            //Set up file ruint list
            values[3] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList*)dataAddr;
            entryList->_numEntries = entries._files.Count;
            dataAddr += entries._files.Count * 8 + 4;

            //Write file entries
            foreach (RSARFileNode file in entries._files)
            {
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                INFOFileHeader* fileHdr = (INFOFileHeader*)dataAddr;
                dataAddr += INFOFileHeader.Size;
                RuintList* list = (RuintList*)dataAddr;
                fileHdr->_entryNumber = -1;
                if (file is RSARExtFileNode)
                {
                    //Make an attempt to get current file size
                    uint s = 0;
                    if (file.ExternalFileInfo.Exists)
                        s = (uint)file.ExternalFileInfo.Length;
                    if (file._extFileSize != s && s != 0) file._extFileSize = s;
                    //Shouldn't matter if 0
                    fileHdr->_headerLen = file._extFileSize;

                    fileHdr->_dataLen = 0;
                    fileHdr->_stringOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr);

                    sbyte* dPtr = (sbyte*)list;
                    file._extPath.Write(ref dPtr);
                    dataAddr += ((int)((VoidPtr)dPtr - (VoidPtr)dataAddr)).Align(4);

                    fileHdr->_listOffset = (uint)((VoidPtr)dataAddr - (VoidPtr)baseAddr);
                    dataAddr += 4; //Empty list
                }
                else
                {
                    fileHdr->_headerLen = (uint)file._headerLen;
                    fileHdr->_dataLen = (uint)file._audioLen;
                    //fileHdr->_stringOffset = 0;
                    fileHdr->_listOffset = (uint)((VoidPtr)list - (VoidPtr)baseAddr);
                    list->_numEntries = file._groups.Count;
                    INFOFileEntry* fileEntries = (INFOFileEntry*)((VoidPtr)list + 4 + file._groups.Count * 8);
                    int z = 0;
                    List<int> used = new List<int>();
                    foreach (RSARGroupNode g in file._groups)
                    {
                        list->Entries[z] = (uint)((VoidPtr)(&fileEntries[z]) - baseAddr);
                        fileEntries[z]._groupId = g._rebuildIndex;
                        int[] all = g._files.FindAllOccurences(file);
                        bool done = false;
                        foreach (int i in all)
                            if (!used.Contains(i))
                            {
                                fileEntries[z]._index = i;
                                used.Add(i);
                                done = true;
                                break;
                            }
                        if (!done)
                            fileEntries[z]._index = g._files.IndexOf(file);
                        z++;
                    }
                    dataAddr = (VoidPtr)fileEntries + file._groups.Count * INFOFileEntry.Size;
                }
            }
            index = 0;
            //Set up group ruint list
            values[4] = (uint)dataAddr - (uint)baseAddr;
            entryList = (RuintList*)dataAddr;
            entryList->_numEntries = entries._groups.Count + 1;
            dataAddr += (entries._groups.Count + 1) * 8 + 4;

            //Write group entries
            foreach (RSAREntryState r in entries._groups)
            {
                r._node._rebuildBase = baseAddr;
                entryList->Entries[index++] = (uint)dataAddr - (uint)baseAddr;
                r._node.Rebuild(dataAddr, r._node._calcSize, true);
                dataAddr += r._node._calcSize;
            }
            //Null group at the end
            entryList->Entries[entries._groups.Count] = (uint)dataAddr - (uint)baseAddr;
            INFOGroupHeader* grp = (INFOGroupHeader*)dataAddr;
            node._nullGroup._rebuildAddr = grp;
            node._nullGroup._rebuildBase = baseAddr;
            *(bint*)(dataAddr + INFOGroupHeader.Size) = 0;
            grp->_entryNum = -1;
            grp->_stringId = -1;
            //grp->_extFilePathRef = 0;
            //grp->_extFilePathRef._dataType = 0;
            grp->_headerLength = 0;
            grp->_waveDataLength = 0;
            grp->_headerOffset = grp->_waveDataOffset = _headerLen + _symbLen + _infoLen + _fileLen;
            grp->_listOffset = (uint)((VoidPtr)(dataAddr + INFOGroupHeader.Size) - baseAddr);
            dataAddr += INFOGroupHeader.Size;
            RuintList* l = (RuintList*)dataAddr;
            INFOGroupEntry* e = (INFOGroupEntry*)((VoidPtr)l + 4 + node._nullGroup.Files.Count * 8);
            l->_numEntries = node._nullGroup.Files.Count;
            int y = 0;
            foreach (RSARFileNode file in node._nullGroup.Files)
            {
                l->Entries[y] = (uint)((VoidPtr)(&e[y]) - baseAddr);
                e[y++]._fileId = file._fileIndex;
                //entries[i]._dataLength = 0;
                //entries[i]._dataOffset = 0;
                //entries[i]._headerLength = 0;
                //entries[i]._headerOffset = 0;
            }
            dataAddr = (VoidPtr)e + node._nullGroup.Files.Count * 0x18;

            //Write footer
            values[5] = (uint)dataAddr - (uint)baseAddr;
            *(INFOFooter*)dataAddr = node.ftr;

            //Set header
            header->_header._tag = INFOHeader.Tag;
            header->_header._length = len = ((int)((dataAddr + INFOFooter.Size) - (baseAddr - 8))).Align(0x20);

            return len;
        }
예제 #10
0
        internal int CalculateSize(RSAREntryList entries, RSARNode node)
        {
            //Header
            _headerLen = 0x40;

            //SYMB, INFO, FILE Headers
            _symbLen = 0x20;
            _infoLen = 0x8;
            _fileLen = 0x20;

            #region SYMB

            //String offsets
            _symbLen += entries._strings.Count * 4;

            //Strings are packed tightly with no trailing pad
            _symbLen += entries._stringLength;

            //Mask entries
            _symbLen += 32; //Headers
            _symbLen += (entries._strings.Count * 2 - 4) * 20; //Entries

            //Align
            _symbLen = _symbLen.Align(0x20);

            #endregion

            #region Info

            //Info ruint collection and ruint list counts
            _infoLen += 0x30;

            int sounds = 4, playerInfo = 4, banks = 4, groups = 4, files = 4;

            //ruint sizes
            sounds += entries._sounds.Count * 8;
            playerInfo += entries._playerInfo.Count * 8;
            groups += entries._groups.Count * 8;
            banks += entries._banks.Count * 8 + 8;
            files += entries._files.Count * 8;

            //Evaluate entries with child offsets
            foreach (RSAREntryState s in entries._sounds)
                sounds += s._node.CalculateSize(true);
            foreach (RSAREntryState s in entries._playerInfo)
                playerInfo += s._node.CalculateSize(true);
            foreach (RSAREntryState s in entries._banks)
                banks += s._node.CalculateSize(true);
            foreach (RSAREntryState s in entries._groups)
                groups += s._node.CalculateSize(true);
            groups += INFOGroupHeader.Size + 4; //Null group at the end
            groups += node._nullGroup.Files.Count * 32;
            foreach (RSARFileNode s in entries._files)
            {
                files += INFOFileHeader.Size + 4;
                if (!(s is RSARExtFileNode))
                    files += s._groups.Count * (8 + INFOFileEntry.Size);
                else
                    files += (s._extPath.Length + 1).Align(4);
            }

            //Footer and Align
            _infoLen = ((_infoLen += (sounds + banks + playerInfo + files + groups)) + 0x10).Align(0x20);

            #endregion

            #region File

            foreach (RSAREntryState r in entries._groups)
            {
                RSARGroupNode g = r._node as RSARGroupNode;
                foreach (RSARFileNode f in g.Files)
                    _fileLen += f.CalculateSize(true);
            }
            foreach (RSARFileNode f in node._nullGroup.Files)
                _fileLen += f.CalculateSize(true);

            //Align
            _fileLen = _fileLen.Align(0x20);

            #endregion

            return _headerLen + _symbLen + _infoLen + _fileLen;
        }