Golden Sun Hacking Community
22, October, 2020, 05:39:58 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: The last working version of the classic TLA Editor is Teawater's unofficial "mapeditor" draft.
 
  Home   Forum   DC Wiki Help Search Calendar Downloads Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: A new Golden Sun Editor  (Read 2510 times)
0 Members and 1 Guest are viewing this topic.

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« on: 10, April, 2020, 08:57:08 AM »

Hi everyone,

I'm currently working on my own Golden Sun Editor (since i'm on a Mac, i can't use the Atrius' editor and GSMagic).

I don't pretend that my editor will be better but it will ll be compatible with most OS as it is develop with React (javascript), so compatible with any web browser.

It is Open Source and i'll post later the link to my repository on GitHub when the project will be more advanced.

I keep you informed  Happy

GitHub repository: https://github.com/RyudoSynbios/golden-sun-editor
[2020-04-22] Golden Sun Editor v1.0.0-alpha.4

> Once downloaded, just extract and open the file index.html on any browser)

IMPORTANT: Make a backup of your rom Exclamation
« Last Edit: 22, April, 2020, 09:39:05 PM by Ryudo » Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #1 on: 10, April, 2020, 09:07:28 AM »

That's great.
I'm not sure how well those run if you use WINE, but it might be an option.
I am happy to see someone besides me working on anything Editor related! So keep up the good work. And prepare for the huge challenge that it probably brings.
A Javascript version?  Can't wait to see it.
Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #2 on: 10, April, 2020, 09:12:03 AM »

Thanks Daddy Poi, i tried WINE but didn't work, maybe because i'm on Catalina.
The first challenge was the text decryption (not brute force, true decoding),  guess the next will be the graphism decryption Happy
Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #3 on: 10, April, 2020, 09:26:26 AM »

Aw. That's unfortunate.
Hm. Well. At least you figured out.
I have three versions of decompression routines for text myself. (All of which decompress all strings at once.)
Oh yeah, and all this is C#.
The main thing is that I don't account for char IDs of 0x100+. (GS2 (U) version does not have any chars from 0x100+ anyway.)

Spoiler for Offset Tree (My favorite one):
        static public byte[] decompText(byte[] src)
        { //, int srcInd) { // int srcPos) {
            //return decompTextOld2(src);
            int total = 0; int total2 = 0;
            DateTime c = DateTime.Now;
            //Scan char data to generate data for faster decompression than old method.
            int asmpchar = Bits.getInt32(src, 0x38578) - 0x8000000;
            int asmptext = Bits.getInt32(src, 0x385DC) - 0x8000000;
            int chardata = Bits.getInt32(src, asmpchar) - 0x08000000;
            int charpntrs = Bits.getInt32(src, asmpchar + 4) - 0x08000000;

            //Do a pre-scan of char tables to determine array sizes.
            int maxLetter = 0;
            int cTreeSize = 0;
            int maxDepth = 0;
            for (int char1 = 0; char1 <= maxLetter; char1++)
            {
                if ((char1 & 0xFF) == 0)
                {
                    chardata = Bits.getInt32(src, asmpchar + (char1 >> 8) * 8) - 0x08000000;
                    charpntrs = Bits.getInt32(src, asmpchar + (char1 >> 8) * 8 + 4) - 0x08000000;
                }
                //if (charpntrs == asmpchar) { break; }
                if (Bits.getInt16(src, charpntrs) == 0x8000) { charpntrs += 2; continue; }
                total2 += 1;
                int charTree = (chardata + Bits.getInt16(src, charpntrs)) << 3; charpntrs += 2;
                int charSlot = charTree - 12;
                int depth = 0;
                while (true)
                {
                    while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) { depth++; cTreeSize++; }
                    int letter = ((Bits.getInt16(src, charSlot >> 3) >> (charSlot & 7)) & 0xFFF); charSlot -= 12; total += 1;
                    cTreeSize++;
                    if (letter > maxLetter) { maxLetter = letter; }
                    if (depth > maxDepth) { maxDepth = depth; }
                    //if ((char1 == 0) && (letter == 7))
                    //    Console.WriteLine("0-7 depth: " + depth);
                    if (depth <= 0) break;
                    --depth;
                } //while (depth > 0);
            }
            //Console.WriteLine("Total letter combos: " + total + "  \nTotal unique letters: " + total2 + "\nMax letter: " + maxLetter + "\nMax depth: " + maxDepth + "\ncTreeSize: " + cTreeSize);
 
            chardata = Bits.getInt32(src, asmpchar) - 0x08000000;
            charpntrs = Bits.getInt32(src, asmpchar + 4) - 0x08000000;
            int[] ctOffsets = new int[maxLetter + 1];// 0x1000];
            int[] cTree = new int[cTreeSize];// 0x10000];
            int[] nodeOffsets = new int[maxDepth]; //0x100]; //For temp use as we label leaves first, and iterate backwards.
            //int[] ctOffsets = new int[0x1000];
            //int[] cTree = new int[0x10000];
            //int[] nodeOffsets = new int[0x100]; //For temp use as we label leaves first, and iterate backwards.
            //int depth = 0;
            int pos = 0;
            for (int char1 = 0; char1 <= maxLetter; char1++)
            {
                if ((char1 & 0xFF) == 0)
                {
                    chardata = Bits.getInt32(src, asmpchar + (char1 >> 8) * 8) - 0x08000000;
                    charpntrs = Bits.getInt32(src, asmpchar + (char1 >> 8) * 8 + 4) - 0x08000000;
                }
                //if (charpntrs == asmpchar) { break; }
                if (Bits.getInt16(src, charpntrs) == 0x8000) { charpntrs += 2; continue; }
                //total2 += 1;
                int charTree = (chardata + Bits.getInt16(src, charpntrs)) << 3; charpntrs += 2;
                int charSlot = charTree - 12;
                int depth = 0;

                ctOffsets[char1] = pos;
                while (true)
                {
                    while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) { nodeOffsets[depth++] = pos++; }
                    cTree[pos++] = -((Bits.getInt16(src, charSlot >> 3) >> (charSlot & 7)) & 0xFFF); charSlot -= 12; //total += 1;

                    if (depth <= 0) break;
                    cTree[nodeOffsets[--depth]] = pos;
                } //while (depth > 0);
            }

            //Console.WriteLine(DateTime.Now - c);
            //c = DateTime.Now;
            int textTree = 0, textLenAddr = 0;
            byte[] des = new byte[0x800000]; int desEntry = 0, desPos = 0xC300;
            for (int srcI = 0; srcI < 12461; srcI++)
            {
                Bits.setInt32(des, desEntry, desPos - 0xC300); desEntry += 4;
                int srcInd = srcI;
                if ((srcInd & 0xFF) == 0)
                {
                    textTree = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3)) - 0x08000000;
                    textLenAddr = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3) + 4) - 0x08000000;
                }
                else
                {
                    int cLen;
                    do
                    {
                        cLen = src[textLenAddr++];
                        textTree += cLen;
                    } while (cLen == 0xFF);
                }
                int initChar = 0, textTree2 = textTree << 3;//, bitnum = 1, val = 0;
                do
                {
                    pos = ctOffsets[initChar];
                    while (cTree[pos] > 0)
                    {
                        if ((src[textTree2 >> 3] >> (textTree2++ & 7) & 1) == 0) { pos++; }
                        else { pos = cTree[pos]; }
                        //--- if using textTree2 = textTree; ---
                        //if (bitnum >= 0x100) { bitnum = 1; textTree2++; }
                        //if ((src[textTree2] & bitnum) == 0) { pos++; }
                        //else { pos = cTree[pos]; }
                        //bitnum <<= 1;
                    }
                    initChar = -cTree[pos]; //bitChar[entry]; val >>= bitLen[entry]; bitnum -= bitLen[entry];
                    des[desPos++] = (byte)initChar;
                    //if (srcI == 5468)
                    //    Console.Write(initChar.ToString("X2")+" ");
                } while (initChar != 0);
            }
            Console.WriteLine(DateTime.Now - c + " (Text Decompression!)");
            return des;
        }

Spoiler for Bit codes version:
        static public byte[] decompTextOld2(byte[] src) { //, int srcInd) { // int srcPos) {
            //return decompTextOld(src);
            int total = 0;
            DateTime c = DateTime.Now;
            int[] bitcode = new int[0x10000];
            byte[] bitLen = new byte[0x10000];
            short[] bitChar = new short[0x10000];
            //Scan char data to generate data for faster decompression than old method.
            int asmpchar = Bits.getInt32(src, 0x38578) - 0x8000000;
            int asmptext = Bits.getInt32(src, 0x385DC) - 0x8000000;
            int chardata = Bits.getInt32(src, asmpchar) - 0x08000000;
            int charpntrs = Bits.getInt32(src, asmpchar + 4) - 0x08000000;
            for (int char1 = 0; char1 < 0x100; char1++) {
                if (charpntrs == asmpchar) { break; }
                if (Bits.getInt16(src, charpntrs) == 0x8000) { charpntrs += 2; continue; }
                int charTree = (chardata + Bits.getInt16(src, charpntrs)) << 3; charpntrs += 2;
                int charSlot = charTree - 12;
                byte bits = 0; int bitC = 0; int entry = (char1 << 8);
                do {
                    while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) { bits++; }
                    bitChar[entry] = (short)((Bits.getInt16(src, charSlot >> 3) >> (charSlot & 7)) & 0xFFF); charSlot -= 12; total += 1;
                    bitLen[entry] = bits; if (bits >= 24) { return decompTextOld(src); }
                    bitcode[entry] = bitC;
                    while (((bitC >> (bits - 1)) & 1) == 1) { bits -= 1; bitC ^= 1 << bits; }
                    bitC |= 1 << (bits - 1);
                    entry += 1;
                } while (bits > 0);
            }
            Console.WriteLine("Total: " + total);
            //Console.WriteLine(DateTime.Now - c);
            //c = DateTime.Now;
            int textTree = 0, textLenAddr = 0;
            byte[] des = new byte[0x800000]; int desEntry = 0, desPos = 0xC300;
            for (int srcI = 0; srcI < 12461; srcI++) {
                Bits.setInt32(des, desEntry, desPos - 0xC300); desEntry += 4;
                int srcInd = srcI;
                if ((srcInd & 0xFF) == 0) {
                    textTree = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3)) - 0x08000000;
                    textLenAddr = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3) + 4) - 0x08000000;
                } else {
                    int cLen;
                    do {
                        cLen = src[textLenAddr++];
                        textTree += cLen;
                    } while (cLen == 0xFF);
                }
                int initChar = 0, bitnum = 0, val = 0, textTree2 = textTree;
                do {
                    while (bitnum < 24) { val |= (int)src[textTree2++] << bitnum; bitnum += 8; }
                    int entry = initChar << 8;
                    while ((val & ((1 << bitLen[entry]) - 1)) != bitcode[entry]) { entry++; }
                    initChar = bitChar[entry]; val >>= bitLen[entry]; bitnum -= bitLen[entry];
                    des[desPos++] = (byte)initChar;
                    //if (desPos >= 0x10000) { break; }
                } while (initChar != 0);
            }
            Console.WriteLine(DateTime.Now - c + " (Text Decompression)");
            return des;
        }

Spoiler for Direct:
        static public byte[] decompTextOld(byte[] src) {
            DateTime c = DateTime.Now;
            int asmpchar = Bits.getInt32(src, 0x38578) - 0x8000000;
            int asmptext = Bits.getInt32(src, 0x385DC) - 0x8000000;
            int chardata = Bits.getInt32(src, asmpchar) - 0x08000000;
            int charpntrs = Bits.getInt32(src, asmpchar + 4) - 0x08000000;
            byte[] des = new byte[0x800000]; int desEntry = 0, desPos = 0xC300;
            for (int srcI = 0; srcI < 12461; srcI++) {
                Bits.setInt32(des, desEntry, desPos - 0xC300); desEntry += 4;
                int srcInd = srcI;

                int textTree = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3)) - 0x08000000;
                int textLenAddr = Bits.getInt32(src, asmptext + ((srcInd >> 8) << 3) + 4) - 0x08000000;
                srcInd &= 0xFF;
                while (srcInd-- != 0) {
                    int cLen;
                    do {
                        cLen = src[textLenAddr++];
                        textTree += cLen;
                    } while (cLen == 0xFF);
                }
                int initChar = 0;

                textTree <<= 3;
                do {
                    int charTree = (chardata + Bits.getInt16(src, charpntrs + (initChar << 1))) << 3;
                    int charSlot = charTree - 12;
                    while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) {
                        if (((src[textTree >> 3] >> (textTree++ & 7)) & 1) == 1) {
                            int depth = 0;
                            while (depth >= 0) {
                                while (((src[charTree >> 3] >> (charTree++ & 7)) & 1) == 0) {
                                    depth++;
                                }
                                charSlot -= 12;
                                depth--;
                            }
                        }
                    }
                    initChar = (Bits.getInt16(src, charSlot >> 3) >> (charSlot & 7)) & 0xFFF;
                    des[desPos++] = (byte)initChar;
                    //do {
                    // n=getNextCharacter(argument0)
                    // if n!=0 {
                    //  if (n<32 || n>ord('~')) {
                    //   if argument2
                    //   { str+='['+string(n)+']'; }
                    //   if argument3 && (n==1 || n==3) && (p<17 || p>20) && p!=26 && p!=29
                    //   { n=0 }
                    //  } else { str+=chr(n); }
                    // }
                    // p=n
                    //} until n=0
                } while (initChar != 0);
            }
            Console.WriteLine(DateTime.Now - c + " (Old Text Decompression)");
            return des;
        }
(I'm not sure if this last one is what you mean by brute force or not.)



And my text compression function was huge... But I like it because it's fast.
Spoiler for Hidden:
        static public void comptext(byte[] src, byte[] dest) {
            DateTime c = DateTime.Now;//.Ticks;
            //Welcome to my Huffman Hamburger! (Scan text, do complex char tables, compress text.)
            //Scan text to generate frequency table.
            ushort char1 = 0, char2 = 0;
            ushort[] freq = new ushort[0x10000]; //We need to know how often each character combination occurs to determine best bit amounts.
            ushort[] clen = new ushort[0x100]; //How many chars each char has associated with it.
            ushort[] clst = new ushort[0x10000]; //Char list in the order they appear in the text.
            int srcEntry = 0;
            while ((Bits.getInt32(src, srcEntry) != 0) || (srcEntry == 0)) { //Set up frequency table and char list (in order displayed in text.)
                int srcPos = 0xC300 + Bits.getInt32(src, srcEntry);
                do {
                    char2 = src[srcPos++];
                    if (freq[char1 * 0x100 + char2]++ == 0) {
                        clst[char1 * 0x100 + clen[char1]++] = char2; //clen[char1]++;// += 1;
                    }
                    //freq[char1 * 0x100 + char2] += 1;
                    char1 = char2;
                } while (char1 != 0); //Change to while < textArray?-- No, go through offset list instead.
                srcEntry += 4;
            }
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/clst.dmp", Array.ConvertAll<short, byte>(clst, delegate(short item) { return (byte)item; }));
            byte[] bitLen = new byte[0x10000]; //int[] bitLen = new int[0x10000];
            int[] bitCode = new int[0x10000];
            int addr2 = 0, chrptlen = 0;
            byte[] chrTbl = new byte[0x8000];
            byte[] chrPtrs = new byte[0x200];
            for (int c1 = 0; c1 < 0x100; c1++) {
                if (clen[c1] == 0) { chrPtrs[(c1 << 1) + 1] = 0x80;  continue; }
                chrptlen = (c1 + 1) << 1;
                //if (c1 > 5) { continue; } //For testing.
                //Sort chars by symbol frequency (simple)
                //See https://en.wikipedia.org/wiki/Sorting_algorithm - Use a Stable one so same-freq chars stay in order.
                //I pick simple Insertion Sort for now, since we are dealing with small sets. (https://en.wikipedia.org/wiki/Insertion_sort)
                for (int i = 1; i < clen[c1]; i++) {
                    ushort x = clst[(c1 << 8) + i];
                    int j = i;
                    while ((j > 0) && (freq[(c1 << 8) + clst[(c1 << 8) + j - 1]] > freq[(c1 << 8) + x])) {
                        clst[(c1 << 8) + j] = clst[(c1 << 8) + j - 1];
                        j = j - 1;
                    }
                    clst[(c1 << 8) + j] = x;
                }
                //Sort chars by node frequency (More advanced)
                int[] symbSort = new int[0x100]; //Basically points to chars in order to be displayed in data.
                int[] symbBits = new int[0x100];
                int[] nodeHead = new int[0x100];
                int[] nodeTail = new int[0x100];
                int[] nodeFreq = new int[0x100]; nodeFreq[0] = 0x7FFFFFFF; nodeFreq[1] = 0x7FFFFFFF; //Ensure unused/node2 when there is none.
                int nodeA = 0, nodeI = 0, symbI = 0;
                if (clen[c1] > 1) {
                    while ((symbI < clen[c1]) || (nodeA < nodeI - 1)) {
                        int symfreq1 = freq[(c1 << 8) + clst[(c1 << 8) + symbI]];
                        int symfreq2 = freq[(c1 << 8) + clst[(c1 << 8) + symbI + 1]];
                        if ((symbI + 1 < clen[c1]) && (symfreq2 <= nodeFreq[nodeA])) { //Symbol - Symbol
                            symbSort[symbI] = symbI + 1;
                            nodeHead[nodeI] = symbI; nodeTail[nodeI] = symbI + 1;
                            nodeFreq[nodeI] = symfreq1 + symfreq2;
                            symbI += 2;
                        } else if ((symbI < clen[c1]) && (symfreq1 <= nodeFreq[nodeA])) { // Symbol - Node
                            symbSort[symbI] = nodeHead[nodeA];
                            nodeHead[nodeI] = symbI; nodeTail[nodeI] = nodeTail[nodeA];
                            nodeFreq[nodeI] = symfreq1 + nodeFreq[nodeA];
                            symbI++; nodeA++;
                        } else if ((nodeA < nodeI - 1) && ((nodeFreq[nodeA + 1] < symfreq1) || ((symbI >= clen[c1])))) { // Node - Node
                            symbSort[nodeTail[nodeA]] = nodeHead[nodeA + 1];
                            nodeHead[nodeI] = nodeHead[nodeA]; nodeTail[nodeI] = nodeTail[nodeA + 1];
                            nodeFreq[nodeI] = nodeFreq[nodeA] + nodeFreq[nodeA + 1];
                            nodeA += 2;
                        } else if (nodeFreq[nodeA] < symfreq1) { // Node - Symbol
                            symbSort[nodeTail[nodeA]] = symbI;
                            nodeHead[nodeI] = nodeHead[nodeA]; nodeTail[nodeI] = symbI;
                            nodeFreq[nodeI] = nodeFreq[nodeA] + symfreq1;
                            symbI++; nodeA++;
                        }
                        symbBits[clst[(c1 << 8) + nodeHead[nodeI++]]] += 1;
                    }
                }
                addr2 += (((clen[c1] * 12) + 4) & -8);
                chrPtrs[(c1 << 1)] = (byte)(addr2 >> 3);
                chrPtrs[(c1 << 1) + 1] = (byte)(addr2 >> 11);
                int addr1 = addr2 - 12;
                byte bitsL = 0;
                //int val = 0;
                //int bitnum = (clen[c1] & 1) * 4;
                int bitC = 0;
                for (int n = clen[c1]; n > 0; n--) {
                    //List chars
                    chrTbl[(addr1 >> 3)] |= (byte)(clst[(c1 << 8) + nodeHead[nodeA]] << (addr1 & 7));
                    chrTbl[(addr1 >> 3) + 1] |= (byte)(clst[(c1 << 8) + nodeHead[nodeA]] >> (8 - (addr1 & 7)));
                    addr1 -= 12;
                    //val |= clst[(c1 << 8) + nodeHead[nodeA]] << bitnum; bitnum += 12;
                    //while (bitnum >= 8) {
                    //    chrTbl[addr1++] = (byte)val; bitnum -= 8;
                    //}
                    //List the char's tree/flags
                    addr2 += symbBits[clst[(c1 << 8) + nodeHead[nodeA]]];
                    chrTbl[addr2 >> 3] |= (byte)(1 << (addr2++ & 7));
                    //Calculate bit lengths for bit code.
                    bitsL += (byte)symbBits[clst[(c1 << 8) + nodeHead[nodeA]]];
                    //bitLen[clst[(c1 << 8) + nodeHead[nodeA]]] = bitsL;
                    bitLen[(c1 << 8) + clst[(c1 << 8) + nodeHead[nodeA]]] = bitsL;
                    //if (symbBits[clst[(c1 << 8) + nodeHead[nodeA]]] == 0) { bitsL -= 1; }
                    //if (c1 == 0) { Console.WriteLine(bitC.ToString("X8") + "   " + bitsL.ToString("X8") + "   " + (char)clst[(c1 << 8) + nodeHead[nodeA]]); }
                    //Generate bitCode table.
                    bitCode[(c1 << 8) + clst[(c1 << 8) + nodeHead[nodeA]]] = bitC;
                    while (((bitC >> (bitsL - 1)) & 1) == 1) { bitsL -= 1; bitC ^= 1 << bitsL; }
                    bitC |= 1 << (bitsL - 1);
                   
                    nodeHead[nodeA] = symbSort[nodeHead[nodeA]];
                }
                addr2 = (addr2 + 8) & -8;
                //Console.WriteLine("\nLetter by node order");
                //for (int zz = 0; zz < clen[c1]; zz++) {
                //    Console.Write(clst[(c1 << 8) + nodeHead[nodeA]].ToString("X4") + " ");
                //    //Console.Write(symbBits[clst[(c1 << 8) + nodeHead[nodeA]]].ToString("X4") + " ");
                //    nodeHead[nodeA] = symbSort[nodeHead[nodeA]];
                //}
                //Console.WriteLine("\nsymbSort");
                //for (int zz = 0; zz < clen[c1]; zz++) {
                //    Console.Write(symbSort[zz].ToString("X4") + " ");
                //}
            }
            /*//-------------------------------------------
            // Making spreadsheet of char tables! (Temp?)
            int[] bmp = new int[0x10000];
            System.Text.StringBuilder strbuild = new System.Text.StringBuilder(0x1000);
            for (int i = 0; i < 0x10000; i++)
            {
                if (freq == 0)
                    continue;
                strbuild.Append((i >> 8).ToString("X2") + (char)9 + (i & 0xFF).ToString("X2") + (char)9);
                strbuild.Append(freq);
                strbuild.Append((char)9);
                //strbuild.Append(bitCode);
                int j = i;
                //int j = 0;j = i & 0xFF00;
                //while (true)
                //{
                //    if (clst[j] == (i & 0xFF))
                //        break;
                //    j++;
                //}
                if (bitLen[j] > 0)
                    strbuild.Append(Convert.ToString(bitCode[j], 2).PadLeft(bitLen[j], '0'));
                strbuild.Append((char)9);
                strbuild.Append(bitLen[j]);
                strbuild.AppendLine();
                /*
                int color = 0xF8F8F8;
                if (((i >> 8) >= 0x41) && ((i >> 8) <= 0x5A))
                    color = 0x00F8F800;
                if (((i >> 8) >= 0x61) && ((i >> 8) <= 0x7A))
                    color = 0x00F8F800;
                if (((i >> 8) >= 0x30) && ((i >> 8) <= 0x39))
                    color = 0x00F8F800;

                if (((i & 0xFF) >= 0x41) && ((i & 0xFF) <= 0x5A))
                    color = 0x00F8F800;
                if (((i & 0xFF) >= 0x61) && ((i & 0xFF) <= 0x7A))
                    color = 0x00F8F800;
                if (((i & 0xFF) >= 0x30) && ((i & 0xFF) <= 0x39))
                    color = 0x00F8F800;

                if (color == 0x00F8F800)
                    color = 0x20A0F8;

                bmp = color;
               
            }
           
            System.Windows.Forms.PictureBox pb = new System.Windows.Forms.PictureBox();

            pb.Image = Bits.PixelsToImage(bmp, 256, 256);
            pb.Image.Save(@"C:\Users\tmttb\Desktop\usedchars.png");
           
            System.IO.File.WriteAllText(@"C:\Users\tmttb\Desktop\usedchars.txt", strbuild.ToString());
            *///-------------------------------------------

            //Finally compress the text.
            int val = 0, bitnum = 0, ctAddr = 0, cstrstart = 0;
            byte[] cText = new byte[src.Length];
            byte[] txtref1 = new byte[0x200]; int tr1Addr = 0;
            byte[] txtref2 = new byte[0x8000]; int tr2Addr = 0;
            srcEntry = 0; char1 = 0;
            while ((Bits.getInt32(src, srcEntry) != 0) || (srcEntry == 0)) {
                if ((srcEntry & 0x3FC) == 0) {
                    Bits.setInt32(txtref1, tr1Addr, ctAddr); tr1Addr += 4;
                    Bits.setInt32(txtref1, tr1Addr, tr2Addr); tr1Addr += 4;
                }
                cstrstart = ctAddr;
                int srcPos = 0xC300 + Bits.getInt32(src, srcEntry); val = 0;
                do {
                    char2 = src[srcPos++];
                    val |= bitCode[(char1 << 8) + char2] << bitnum;
                    bitnum += bitLen[(char1 << 8) + char2];
                    while (bitnum >= 8) {
                        cText[ctAddr++] = (byte)val; val >>= 8; bitnum -= 8;
                    }
                    //if (freq[char1 * 0x100 + char2]++ == 0) {
                    //    clst[char1 * 0x100 + clen[char1]++] = char2; //clen[char1]++;// += 1;
                    //}
                    //freq[char1 * 0x100 + char2] += 1;
                    //if (srcEntry == 0) { Console.WriteLine(bitCode[(char1 << 8) + char2].ToString("X8") + "   " + bitLen[(char1 << 8) + char2].ToString("X8")); }
                    char1 = char2;
                } while (char1 != 0); //Change to while < textArray?-- No, go through offset list instead.
                srcEntry += 4; if (bitnum != 0) { cText[ctAddr++] = (byte)val; bitnum = 0; }
                while ((ctAddr - cstrstart) > 0xFE) { txtref2[tr2Addr++] = 0xFF; cstrstart += 0xFF; }
                txtref2[tr2Addr++] = (byte)(ctAddr - cstrstart); //cstrstart = ctAddr;
            }
            //Now insert everything into the ROM.
            int insAddr = 0xFA0000;
            int loc1 = insAddr;
            Array.Copy(chrTbl, 0, dest, insAddr, addr2 >> 3); insAddr += addr2 >> 3;
            insAddr = (insAddr + 1) & -2;
            int loc2 = insAddr;
            Array.Copy(chrPtrs, 0, dest, insAddr, chrptlen); insAddr += chrptlen;
            insAddr = (insAddr + 3) & -4;
            Bits.setInt32(dest, 0x38578, 0x08000000 + insAddr);
            Bits.setInt32(dest, insAddr, 0x08000000 + loc1); insAddr += 4;
            Bits.setInt32(dest, insAddr, 0x08000000 + loc2); insAddr += 4;
            loc1 = insAddr;
            Array.Copy(cText, 0, dest, insAddr, ctAddr); insAddr += ctAddr;
            loc2 = insAddr;
            Array.Copy(txtref2, 0, dest, insAddr, tr2Addr); insAddr += tr2Addr;
            insAddr = (insAddr + 3) & -4;
            Bits.setInt32(dest, 0x385DC, 0x08000000 + insAddr);
            for (int a = 0; a < tr1Addr; a += 8) {
                Bits.setInt32(dest, insAddr + a, 0x08000000 + Bits.getInt32(txtref1, a) + loc1);
                Bits.setInt32(dest, insAddr + a + 4, 0x08000000 + Bits.getInt32(txtref1, a + 4) + loc2);
            }
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/txtromtest.gba", dest);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/txtref1.dmp", txtref1);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/txtref2.dmp", txtref2);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/cText.dmp", cText);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/chrPtrs.dmp", chrPtrs);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/chrTbl.dmp", chrTbl);
            //System.IO.File.WriteAllBytes("C:/Users/Tea/Desktop/bitLen.dmp", bitLen);
            //DateTime c = DateTime.Now;//.Ticks;
            Console.WriteLine((DateTime.Now - c).ToString());
        }
« Last Edit: 10, April, 2020, 09:40:30 AM by Daddy Poi » Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #4 on: 10, April, 2020, 09:43:35 AM »

No it's ok, i learned a lot with this Huffman Algorithm Happy

You did a great job! I have to improve my decryption script, it's a bit slow.

I didn't work on the compression part, i want to have something working on the editor first Happy
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #5 on: 10, April, 2020, 06:01:08 PM »

As promise, here's some screenshots.

The design is not definitive, i'm not webdesigner so it's a bit complicated for me.

The order of fields is subject to change, i just put them randomly.



* 01.Open File.png (47.33 KB, 2880x1532 - viewed 128 times.)

* 02.Items.png (188.52 KB, 2880x1532 - viewed 122 times.)

* 03.Abilities.png (162.65 KB, 2880x1532 - viewed 107 times.)

* 04.Djinnis.png (104.5 KB, 2880x1532 - viewed 111 times.)
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #6 on: 10, April, 2020, 06:02:27 PM »

The second part of screenshots.

Also, it's now possible to load an USA/English rom (of the first Golden Sun).


* 05.Summons.png (129.04 KB, 2880x1532 - viewed 116 times.)

* 06.Enemies.png (193.89 KB, 2880x1532 - viewed 109 times.)

* 07.Groups.png (149.24 KB, 2880x1532 - viewed 106 times.)

* 08.Texts.png (209.75 KB, 2880x1532 - viewed 122 times.)
Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #7 on: 10, April, 2020, 11:19:57 PM »

Would be interesting to see if your project could completely replace gsmagic some day. I guess we'll see. I think I felt more comfortable working with C# than with Javascript, but if I get use to Javascript, then I guess it could work out.


Djinnis = Typo? "Djinn" would be the plural form. ("Djinni" is the singular.)
And I believe it to be pronounced as Jen/Jenny.
« Last Edit: 10, April, 2020, 11:33:56 PM by Daddy Poi » Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #8 on: 11, April, 2020, 07:28:28 AM »

We'll see, i have time for this project since the confinement in France, buy i'll have less time after, that's why the project is Open Source Happy

Do you have some screenshots of GSMagic? I can't open it, even with VirtualBox and i can't find images / videos.

Thank's for the correction Venus Djinni
Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #9 on: 11, April, 2020, 09:50:07 AM »

Might take a lot of screenshots to show everything... so won't go over everything right now, but I guess I can give you a few...

It may be kind of messy. - And plenty of work may need to be done.
But here's what Heightmap looks like. (You can also edit them too, if you are on the Height table page in subwindow.)
And here's what the Events may look like.

In both, it's done in three layers, so to see the other layers, hit 1/2/3 on keyboard. (Layers may be blank if it wasn't needed.)

And third image is what the subwindow looks like when you can put event tiles in the map. I have this here to also show that each tile lists the frequency of how often they were used in the map. (The tile uses a brighter color if the frequency is at least 1... with the exception of ID 0.)
The latest release version actually does 16 columns instead of 10.... but I decided to try 10, and I haven't finished fixing it. Heheh.



And the Editors windows is also kind of messy/needs work. Has a few tables, and I consider it slightly less interesting, so didn't include screenshots. (PLus, I'm limited to 4 per post, so...)


* gsmagicheightmap.png (158 KB, 761x898 - viewed 112 times.)

* gsmagiceventmap.png (725.76 KB, 1053x1048 - viewed 125 times.)

* gsmagiceventwindow.png (7.99 KB, 529x800 - viewed 120 times.)
« Last Edit: 11, April, 2020, 10:02:12 AM by Daddy Poi » Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #10 on: 11, April, 2020, 10:22:01 AM »

Great, thanks Daddy Poi !
Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #11 on: 11, April, 2020, 10:25:08 AM »

You are welcome!
(FYI - Daddy Poi is a reference to that old guy in Kandarian temple (or whatever it is called.), and how a few of us joked about him on Discord way back. Heheh.)



Sounds like daddy boy to me, kinda.
« Last Edit: 11, April, 2020, 10:28:39 AM by Daddy Poi » Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #12 on: 11, April, 2020, 11:25:19 AM »

Haha, with the French version, i don't have this reference Happy

Daddy Boy: it's the sound that i had on saying your pseudo in my head xD
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #13 on: 12, April, 2020, 01:29:27 PM »

Hi, you can find a link to download the current state of the project on my first post.

Please, read carefully all the post Exclamation

Don't hesitate to push any problem or idea of amelioration Happy
« Last Edit: 12, April, 2020, 02:01:13 PM by Ryudo » Logged
View Profile
Daddy Poi's Oily Gorillas
Fox McCloud, the Hacking Doctor
Mercury Clan

Prodigy
*

Coins: 1002
Offline Offline

I am: certainly not a Gallant!
Clan Position: Head Gallant
Posts: 2491

« Reply #14 on: 12, April, 2020, 03:52:19 PM »

Seems blank for Microsoft Edge and Internet Explorer. (Hopefully I'm not using outdated versions? *shrug*)

Seems to work with Google Chrome and Firefox, though. So that's good.
Logged

Golden Sun Docs: Broken Seal - The Lost Age - Dark Dawn | Mario Sports Docs: Mario Golf & Mario Tennis | Misc. Docs
Refer to Yoshi's Lighthouse for any M&L hacking needs...

Sometimes I like to compare apples to oranges. (Figuratively) ... They are both fruits, but which one would you eat more? (If taken literally, I'd probably choose apples.)
Maybe it is over-analyzing, but it doesn't mean the information is useless.


The only GS Discord servers with significance are:
Golden Sun Hacking Community
GS Speedrunning
/r/Golden Sun
GS United Nations
Temple of Kraden

Can you believe how small the Golden Sun Community is?

2+2=5 Don't believe me? Those are rounded decimal numbers. Take that, flat earth theorists! :)
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #15 on: 12, April, 2020, 05:02:06 PM »

Yep, didn't check on IE and Edge, i'll check later !

There's also a standalone version but i only can generate it like a MacOS application (for the moment).

Thanks for your test !
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #16 on: 15, April, 2020, 01:42:09 PM »

Golden Sun Editor v1.0.0-alpha.2
- Improve Dropzone
- Improve speed navigation
- Improve translations
- Add icon and favicon
- Add About
- Allow to change language (English/French)
- Allow to Eject rom
- Temporary fix incomplete CircularProgress
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #17 on: 17, April, 2020, 08:27:37 PM »

Golden Sun Editor v1.0.0-alpha.3
- Add compatibility with Golden Sun 1 [ Germany / Italy / Spain ]
- Add Shops
- Add Classes
- Add Sprites
- Add icons (from rom) on Abilities and Items
- Improve header design
Logged
View Profile

Novice Member
*

Coins: 2
Offline Offline

Posts: 14

« Reply #18 on: 22, April, 2020, 09:38:31 PM »

Golden Sun Editor v1.0.0-alpha.4
- Add Maps (just names)
- Add Party Members
- Improve Shops
- Add type and uses on Abilities
- Translate attributes from rom on Abilities
- Tabs are now scrollable
Logged
View Profile
Pages: [1]   Go Up
  Print  
 
Jump to:  

Chatbox
13, October, 2020, 11:19:21 AM
MaxiPower: first chapter of my golden sun inspired webtoon is now live. be cool if yas could check it out. https://www.webtoons.com/en/challenge/legacy-of-the-lost-dragoon/the-northern-reaches/viewer?title_no=508487&episode_no=6
31, August, 2020, 08:40:32 AM
Daddy Poi's Oily Gorillas: Being able to convert IPS files to text files to also supporting commenting, and convert back to IPS after changes.... sounds like a fun strategy? 
27, August, 2020, 10:37:30 PM
Salanewt: Hey, thanks! 
25, August, 2020, 12:59:22 AM
Foreclosure: Yo! Looking forward for this AI OVerhaul patch when it's finished :) :) 
19, August, 2020, 07:00:17 PM
Salanewt: That's awesome! I'm pretty good; been working on an AI Overhaul project and have made some nice progress in the past couple weeks; the goal for tonight is to add Deadbeard to GS2 and then I can move onto something new.
19, August, 2020, 01:14:56 PM
Awec: Ye not bad, just checked back in for updates on GS Reloaded really. Although now I'm looking back through some of my old forum posts, which is fun :D how are you?
19, August, 2020, 01:43:07 AM
Salanewt: It sure is! How have you been?
16, August, 2020, 09:40:57 AM
Awec: Yo nice to see this forum is still going
14, August, 2020, 09:06:44 PM
Salanewt: Hey! How goes it?
01, August, 2020, 01:31:53 PM
KyleRunner: Hello, people!
08, July, 2020, 08:57:11 PM
Salanewt: That awkward feeling when almost a quarter of a year goes by without anyone posting a message in this chatbox.
27, April, 2020, 07:54:10 PM
Daddy Poi's Oily Gorillas: I'm having a thought. So I know Atrius's editor is slow at saving sprites.... So I've been thinking.   I am considering another console program.  This time, for importing and exporting sprites/animations. Image files (for sprites), binary files (for animation data), and maybe binary or text files for Settings. Would certainly be cool if it works out. - Console programs are fun, when you can (at least temporarily) cheat out making a full interface editor for them. =P
25, April, 2020, 10:42:07 PM
Daddy Poi's Oily Gorillas: Tried to list those in order of importance, but anyway....
25, April, 2020, 10:37:59 PM
Daddy Poi's Oily Gorillas: GSHC, GS Speedrunning, /r/Golden Sun, GS United Nations, ToK.  Sixth one is border-line I'm not sure.
25, April, 2020, 08:00:21 PM
Daddy Poi's Oily Gorillas: (low as in <100)
25, April, 2020, 08:00:04 PM
Daddy Poi's Oily Gorillas: So while there are quite a few GS Communities out there. There are only up to maybe ~6 Discords worth even the consideration of joining, I think. Most of the rest of them have a fairly low member count. (Of which I can tell?)
14, April, 2020, 10:49:35 AM
Daddy Poi's Oily Gorillas: The Essential Age could be what it stands for?
13, April, 2020, 05:23:32 PM
Misery: Tea editor... that's a cute name for it
01, April, 2020, 02:42:48 AM
JupiterDjinn: Also my browser is sending two o f my messages srry.
01, April, 2020, 02:42:06 AM
JupiterDjinn: Just got the reply. Ok my question is: how can I get the tea editor on Android, because I already have an emulator. But no computer.
31, March, 2020, 07:18:29 PM
Salanewt: Sure thing!
31, March, 2020, 03:38:27 PM
JupiterDjinn: Can I have a question answered?
28, March, 2020, 12:50:13 AM
Salanewt: I want to shrink it down in size later, but yup!
26, March, 2020, 03:24:45 PM
Daddy Poi's Oily Gorillas: The news box is back? :D
19, March, 2020, 05:59:16 PM
Salanewt: Nice work hiding the searchbots Atrius!
19, March, 2020, 04:23:34 PM
Salanewt: I was wondering when I said that stuff! May need to work it out with Kain.
19, March, 2020, 07:03:05 AM
Daddy Poi's Oily Gorillas: (The simplest being to not accept char IDs pass 255, I think.)
19, March, 2020, 05:33:15 AM
Daddy Poi's Oily Gorillas: Heheh.... I'm just testing. You pretty much gave it away. Hahah. It seems to look fairly convincing, but I'm sure there's an easy solution to preventing it.
19, March, 2020, 05:28:50 AM
Atrius: Whelp, there it goes... Just what I didn't want.  Have fun with that I guess...   
19, March, 2020, 05:20:25 AM
Daddy Poi's Oily Gorillas: So like. Replace the "e" with another "e"? Alright. Gotcha.

Affiliates
Temple of Kraden Golden Sunrise
Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.129 seconds with 23 queries.