Untitled

mail@pastecode.io avatar
unknown
csharp
2 years ago
9.7 kB
3
Indexable
Never
// Open file
            string sourcePath;

            using (OpenFileDialog dialog = new OpenFileDialog())
            {
                // If user closes dialog, return to main window
                if (dialog.ShowDialog(this) != DialogResult.OK)
                {
                    return;
                }

                sourcePath = dialog.FileName;
            }

            string sFile = File.ReadAllText(sourcePath);
            string[] xMap = File.ReadAllLines("xmap.txt");
            List<string> linkOrderLines = new List<string>();

            Regex symbolRegex = new Regex(@"(?<address>[0-9A-F]{8})\s+(?<size>[0-9A-F]{8})\s\.(?<section>text|(ro)*data|bss)\s+(?<name>.+?)\s+\((?<source>.+)\)", RegexOptions.ExplicitCapture | RegexOptions.Compiled);

            int overlayNumber = Convert.ToInt32(Path.GetFileNameWithoutExtension(sourcePath).Replace("overlay", ""));
            int i = 0;

            // Go to overlay section
            while (!xMap[i++].Contains($"# .overlay{overlayNumber}"))
                continue;

            Debug.WriteLine("----- FOUND OVERLAY IN XMAP");

            List<Symbol> textSymbols = new List<Symbol>();
            List<Symbol> rodataSymbols = new List<Symbol>();
            List<Symbol> dataSymbols = new List<Symbol>();
            List<Symbol> bssSymbols = new List<Symbol>();

            while (!xMap[i++].Contains($"SDK_OVERLAY.overlay{overlayNumber}.BSS_END"))
            {
                if (symbolRegex.IsMatch(xMap[i]))
                {              
                    Match m = symbolRegex.Match(xMap[i]);

                    Symbol s = new Symbol();

                    s.address = Convert.ToInt32(m.Groups["address"].Value, 16);
                    s.size = Convert.ToInt32(m.Groups["size"].Value, 16);
                    s.section = m.Groups["section"].Value;
                    s.name = m.Groups["name"].Value.Trim();
                    s.source = m.Groups["source"].Value.Trim();
                    s.offset = 0;


                    if (s.size == 0)
                        continue;

                    switch (s.section)
                    {
                        case "rodata":
                            rodataSymbols.Add(s);
                            break;

                        case "data":
                            dataSymbols.Add(s);
                            break;

                        case "bss":
                            bssSymbols.Add(s);
                            break;

                        default:
                            textSymbols.Add(s);
                            break;
                    }
                }
            }


            // Fix sizes or offsets
            for (i = 0; i < textSymbols.Count - 1; i++)
                textSymbols[i].size = textSymbols[i + 1].address - textSymbols[i].address;

            for (i = 0; i < rodataSymbols.Count; i++)
            {
                rodataSymbols[i].offset = rodataSymbols[i].address - rodataSymbols[0].address;
            }

            for (i = 0; i < dataSymbols.Count; i++)
            {
                dataSymbols[i].offset = dataSymbols[i].address - dataSymbols[0].address;
            }

            for (i = 0; i < bssSymbols.Count - 1; i++)
            {
                bssSymbols[i].size = bssSymbols[i+1].address - bssSymbols[i].address;
            }

            // Split by file
            var textByFile = textSymbols.GroupBy(s => s.source);
            var rodataByFile = rodataSymbols.GroupBy(s => s.source);
            var dataByFile = dataSymbols.GroupBy(s => s.source);
            var bssByFile = bssSymbols.GroupBy(s => s.source);

            // Text headers
            string textHeader = @"	.include ""macros/function.inc""
	.include ""global.inc""

";
            Debug.WriteLine("TEXT FILES: " + textByFile.Count());

            List<string> groupKeys = new List<string>();


            foreach (var textgroup in textByFile)
                if (!groupKeys.Contains(textgroup.Key))
                    groupKeys.Add(textgroup.Key);

            foreach (var rodatagroup in rodataByFile)
                if (!groupKeys.Contains(rodatagroup.Key))
                    groupKeys.Add(rodatagroup.Key);

            foreach (var datagroup in dataByFile)
                if (!groupKeys.Contains(datagroup.Key))
                    groupKeys.Add(datagroup.Key);

            foreach (var bssgroup in bssByFile)
                if (!groupKeys.Contains(bssgroup.Key))
                    groupKeys.Add(bssgroup.Key);

            // Write splits
            foreach (string group in groupKeys)
            {
                string text = "\t.text\r\n\r\n\r\n\t";

                foreach (var textgroup in textByFile)
                {
                    text += Regex.Match(sFile, $@"(thumb|arm)_func_start ov{overlayNumber}_{textgroup.First().address.ToString("X8")}[\w\W]+(thumb|arm)_func_end ov{overlayNumber}_{textgroup.Last().address.ToString("X8")}").Value;
                }
                
                string rodata = "\t.rodata\r\n\r\n\r\n";
        
                foreach (var rodatagroup in rodataByFile)
                {
                    if (rodatagroup.Key != group)
                        continue;

                    for (int j = 0; j < rodatagroup.Count(); j++)
                    {
                        Symbol symbol = rodatagroup.ElementAt(j);

                        string symbolString = "\t" + $".global Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}\r\n";
                        symbolString += $"Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}: ; 0x{symbol.address.ToString("X8")}\r\n\t";

                        if (j == 0)
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_rodata.bin"", 0x{symbol.offset.ToString("X")}, 0x{symbol.size.ToString("X")}" + "\r\n";

                        else if (j == rodatagroup.Count() - 1)
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_rodata.bin"", 0x{symbol.offset.ToString("X")}, 0x{symbol.size.ToString("X")}" + "\r\n";

                        else
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_rodata.bin"", 0x{symbol.offset.ToString("X")}, 0x{rodatagroup.ElementAt(j+1).offset.ToString("X")} - 0x{symbol.offset.ToString("X")}" + "\r\n";

                        rodata += symbolString + "\r\n";
                    }
                }

                string data = "\t.data\r\n\r\n\r\n";

                foreach (var datagroup in dataByFile)
                {
                    if (datagroup.Key != group)
                        continue;

                    for (int j = 0; j < datagroup.Count(); j++)
                    {
                        Symbol symbol = datagroup.ElementAt(j);

                        string symbolString = "\t" + $".global Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}\r\n";
                        symbolString += $"Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}: ; 0x{symbol.address.ToString("X8")}\r\n\t";

                        if (j == 0)
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_data.bin"", 0x0, 0x{symbol.size.ToString("X")}" + "\r\n";

                        else if (j == datagroup.Count() - 1)
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_data.bin"", 0x{symbol.offset.ToString("X")}, 0x{symbol.size.ToString("X")}" + "\r\n";

                        else
                            symbolString += $@".incbin ""incbin/overlay{overlayNumber}_data.bin"", 0x{symbol.offset.ToString("X")}, 0x{datagroup.ElementAt(j + 1).offset.ToString("X")} - 0x{symbol.offset.ToString("X")}" + "\r\n";

                        data += symbolString + "\r\n";
                    }
                }

                string bss = "\t.bss\r\n\r\n\r\n";

                foreach (var bssgroup in bssByFile)
                {
                    if (bssgroup.Key != group)
                        continue;

                    for (int j = 0; j < bssgroup.Count(); j++)
                    {
                        Symbol symbol = bssgroup.ElementAt(j);

                        string symbolString = "\t" + $".global Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}\r\n";

                        symbolString += $"Unk_ov{overlayNumber}_{symbol.address.ToString("X8")}: ; 0x{symbol.address.ToString("X8")}\r\n\t";
                        symbolString += $".space 0x{symbol.size.ToString("X")}" + "\r\n";

                        bss += symbolString + "\r\n";
                    }
                }

                string content = textHeader + "\t";

                if (text != "\t.text\r\n\r\n\r\n\t")
                    content += "\r\n\r\n" + text;

                if (rodata != "\t.rodata\r\n\r\n\r\n")
                    content += "\r\n\r\n" + rodata;

                if (data != "\t.data\r\n\r\n\r\n")
                    content += "\r\n" + data;

                if (bss != "\t.bss\r\n\r\n\r\n")
                    content += "\r\n" + bss;


                string firstSymbol = Regex.Match(content, $@"ov{overlayNumber}_[0-9A-F]+").Value;

                linkOrderLines.Add($"Object asm/{firstSymbol}.o");
                File.WriteAllText($"split\\{firstSymbol}.s", content);
            }

            File.WriteAllLines($"ov{overlayNumber}_link_order.txt", linkOrderLines);
        }