public unsafe static UnitSettings[] getUnitSettings(String filePath)
        {
            EUDSettings es = new EUDSettings();

            es.action         = (byte)6;
            es.outputFilePath = (byte *)0;
            es.inputFilePath  = toByteArray(filePath);
            try {
                run(&es); // Run extraction
                UnsafeReadBuffer rb  = new UnsafeReadBuffer(es.outputFilePath);
                UnitSettings[]   ret = new UnitSettings[2];
                for (int i = 0; i < 2; i++)
                {
                    ret[i].used          = rb.readByteArray(228);
                    ret[i].hp            = rb.readIntArray(228);
                    ret[i].shield        = rb.readShortArray(228);
                    ret[i].armor         = rb.readByteArray(228);
                    ret[i].build_time    = rb.readShortArray(228);
                    ret[i].mineral_cost  = rb.readShortArray(228);
                    ret[i].gas_cost      = rb.readShortArray(228);
                    ret[i].str_unit_name = rb.readShortArray(228);
                    ret[i].weapon_damage = rb.readShortArray(130);
                    ret[i].upgrade_bonus = rb.readShortArray(130);
                }
                es.action = (byte)3;
                run(&es); // Free the array data string
                return(ret);
            } catch (Exception) {
            }
            return(null);
        }
        public unsafe static Slot[] getSlots(String filePath)
        {
            EUDSettings es = new EUDSettings();

            es.action         = (byte)5;
            es.outputFilePath = (byte *)0;
            es.inputFilePath  = toByteArray(filePath);
            try {
                run(&es); // Run extraction
                UnsafeReadBuffer rb  = new UnsafeReadBuffer(es.outputFilePath);
                Slot[]           ret = new Slot[12];
                for (int i = 0; i < 12; i++)
                {
                    byte b = (byte)rb.readByte();
                    if (b >= 0 && b < 9)
                    {
                        ret[i] = (Slot)b;
                    }
                    else
                    {
                        ret[i] = Slot.Invalid;
                    }
                }

                es.action = (byte)3;
                run(&es); // Free the array data string
                return(ret);
            } catch (Exception) {
            }
            return(null);
        }
        public static unsafe MapString[] getStrings(String filePath, String encoding)
        {
            TranslationStructure es = new TranslationStructure();

            es.action         = (byte)2;
            es.outputFilePath = (byte *)0;
            es.inputFilePath  = toByteArray(filePath, Settings.defaultEncoding);
            try {
                run(&es); // Run extraction

                killByteArray(es.inputFilePath);
                UnsafeReadBuffer rb = new UnsafeReadBuffer(es.stringData);

                int         totalStrings = rb.readInt();
                MapString[] result       = new MapString[totalStrings];
                for (int i = 0; i < totalStrings; i++)
                {
                    result[i] = readMapString(rb, encoding);
                }

                // Sort by index
                bool changed = true;
                while (changed)
                {
                    changed = false;
                    for (int i = 1; i < result.Length; i++)
                    {
                        MapString p0 = result[i - 1];
                        MapString p1 = result[i];
                        if (p0.mapIndex > p1.mapIndex)
                        {
                            changed       = true;
                            result[i - 1] = p1;
                            result[i]     = p0;
                        }
                    }
                }

                for (int i = 0; i < result.Length; i++)
                {
                    //result[i].storageIndex = i;
                }
                es.action = (byte)3;
                run(&es); // Free the array data string

                return(result);
            } catch (Exception) {
            }
            return(null);
        }
        private static unsafe void run(TranslationStructure *settings)
        {
            unsafe {
                // Move to unmanaged memory

                //int dataSize = Marshal.SizeOf<EUDSettings>(settings);

                int               dataSize = 1024; // Stupid but works
                IntPtr            ptr      = Marshal.AllocHGlobal(dataSize);
                byte *            data     = (byte *)ptr;
                UnsafeWriteBuffer wb       = new UnsafeWriteBuffer(data);
                wb.writeByte(settings->action);
                wb.writeBytePtr(settings->inputFilePath);
                wb.writeBytePtr(settings->outputFilePath);

                wb.writeBytePtr(settings->stringData);
                wb.writeInt(settings->stringDataLength);

                wb.writeInt(settings->useCondition);
                wb.writeByte(settings->repack);

                wb.writeByte(settings->result);

                // Process
                IntPtr ms = (IntPtr)data;
                Process(ms);

                UnsafeReadBuffer rb = new UnsafeReadBuffer(data);
                settings->action = (byte)rb.readByte();

                settings->inputFilePath  = rb.readBytePtr();
                settings->outputFilePath = rb.readBytePtr();

                settings->stringData       = rb.readBytePtr();
                settings->stringDataLength = rb.readInt();

                settings->useCondition = rb.readInt();
                settings->repack       = (byte)rb.readByte();

                settings->result = (byte)rb.readByte();

                Marshal.FreeHGlobal(ptr);
            }
        }
        public static unsafe String[] getMapNameAndDescription(String filePath)
        {
            String      mapName        = "";
            String      mapDescription = "";
            EUDSettings es             = new EUDSettings();

            es.action         = (byte)7;
            es.outputFilePath = (byte *)0;
            es.inputFilePath  = toByteArray(filePath);
            try {
                run(&es); // Run extraction
                UnsafeReadBuffer rb = new UnsafeReadBuffer(es.outputFilePath);
                mapName        = rb.readString();
                mapDescription = rb.readString();
                es.action      = (byte)3;
                run(&es); // Free the array data string
            } catch (Exception) {
            }
            return(new String[] { mapName, mapDescription });
        }
        private static MapString readMapString(UnsafeReadBuffer rb, String encoding)
        {
            MapString ms = new MapString();

            ms.mapIndex = rb.readInt();

            ms.str = rb.readString(encoding);
            ms.isMapDescription = rb.readByte() == 1 ? true : false;
            ms.isMapName        = rb.readByte() == 1 ? true : false;

            ms.unitIndexs              = rb.readIntArray(rb.readInt());
            ms.switchIndexes           = rb.readIntArray(rb.readInt());
            ms.locationIndexes         = rb.readIntArray(rb.readInt());
            ms.triggerActionIndexes    = rb.readIntArray(rb.readInt());
            ms.triggerCommentIndexes   = rb.readIntArray(rb.readInt());
            ms.briefingActionIndexes   = rb.readIntArray(rb.readInt());
            ms.briefingCommentsIndexes = rb.readIntArray(rb.readInt());
            ms.forceNamesIndexes       = rb.readIntArray(rb.readInt());

            return(ms);
        }
        private static ProcessFunc _Process = null; // DLL Method


        public unsafe static SoundFiles getWavs(Settings settings)
        {
            if (settings.inpuPath == null)
            {
                throw new Exception("Invalid file");
            }
            else if (!File.Exists(settings.inpuPath))
            {
                throw new Exception("File doesn't exist");
            }

            EUDSettings es = new EUDSettings();

            es.action        = (byte)2;
            es.inputFilePath = toByteArray(settings.inpuPath);
            List <SoundFile> insides = new List <SoundFile>();
            List <SoundFile> maps    = new List <SoundFile>();
            Exception        e       = null;

            try {
                run(&es); // Get the array data string
                UnsafeReadBuffer rb = new UnsafeReadBuffer(es.outputFilePath);
                insides = fromListOfStringsFromBuffer("Native", rb, true, false);
                maps    = fromListOfStringsFromBuffer(new FileInfo(settings.inpuPath).Name, rb, false, true);

                es.action = (byte)3;
                run(&es); // Free the array data string
            } catch (Exception ex) {
                e = ex;
            }
            killByteArray(es.inputFilePath);
            if (e != null)
            {
                throw e;
            }
            return(new SoundFiles(insides, maps));
        }
        private static unsafe List <SoundFile> fromListOfStringsFromBuffer(String sourceName, UnsafeReadBuffer rb, Boolean isNative, Boolean isMapFile)
        {
            int totalFiles          = rb.readInt();
            List <SoundFile> result = new List <SoundFile>();

            for (int i = 0; i < totalFiles; i++)
            {
                StringBuilder fileNameSb = new StringBuilder();
                int           stringLen  = rb.readInt();
                for (int o = 0; o < stringLen; o++)
                {
                    byte b = (byte)rb.readByte();
                    fileNameSb.Append((char)b);
                }
                int    dataLength = rb.readInt();
                byte[] data       = new byte[dataLength];
                for (int o = 0; o < dataLength; o++)
                {
                    byte b = (byte)rb.readByte();
                    data[o] = b;
                }
                int    duration = rb.readInt();
                String fileName = fileNameSb.ToString();
                if (fileName.ToLower().EndsWith(".wav") || fileName.ToLower().EndsWith(".ogg"))
                {
                    result.Add(new SoundFile(sourceName, fileName, data, duration, isNative, isMapFile, false));
                }
            }
            return(result);
        }
        private static unsafe void run(EUDSettings *settings)
        {
            unsafe
            {
                // Move to unmanaged memory

                //int dataSize = Marshal.SizeOf<EUDSettings>(settings);

                int               dataSize = 1024; // Stupid but works
                IntPtr            ptr      = Marshal.AllocHGlobal(dataSize);
                byte *            data     = (byte *)ptr;
                UnsafeWriteBuffer wb       = new UnsafeWriteBuffer(data);
                wb.writeByte(settings->action);
                wb.writeBool(settings->addTouchRevive);
                wb.writeBool(settings->useDefaultGunShot);
                wb.writeBool(settings->useDefaultBackgroundMusic);
                wb.writeBool(settings->enableVisor);
                wb.writeBool(settings->enableBarrier);
                wb.writeBool(settings->addLeaderboard);
                wb.writeBool(settings->addTimeLock);

                wb.writeBool(settings->useSanctuaryColors);

                wb.writeBool(settings->recalculateHPAndDamage);
                wb.writeBool(settings->muteUnits);

                wb.writeBytePtr(settings->GunShotWavFilePath);
                wb.writeBytePtr(settings->VisorUsageFilePath);
                wb.writeBytePtr(settings->BackgroundWavFilePath);

                wb.writeBytePtr(settings->TimeLockMessage);
                wb.writeBytePtr(settings->TimeLockFrom);
                wb.writeBytePtr(settings->TimeLockTo);
                wb.writeBytePtr(settings->inputFilePath);
                wb.writeBytePtr(settings->outputFilePath);

                wb.writeShort(settings->EMPDamage);

                wb.writeInt(settings->result);
                wb.writeBytePtr(settings->preferredUnitSettings);
                wb.writeBytePtr(settings->ignoreArmors);

                wb.writeBytePtr(settings->mapName);
                wb.writeBytePtr(settings->description);
                wb.writeBytePtr(settings->objectives);
                wb.writeBool(settings->useObjectives);

                // Process
                IntPtr ms = (IntPtr)data;
                Process(ms);

                UnsafeReadBuffer rb = new UnsafeReadBuffer(data);
                settings->action                    = (byte)rb.readByte();
                settings->addTouchRevive            = rb.readBool();
                settings->useDefaultGunShot         = rb.readBool();
                settings->useDefaultBackgroundMusic = rb.readBool();
                settings->enableVisor               = rb.readBool();
                settings->enableBarrier             = rb.readBool();
                settings->addLeaderboard            = rb.readBool();
                settings->addTimeLock               = rb.readBool();
                settings->useSanctuaryColors        = rb.readBool();
                settings->recalculateHPAndDamage    = rb.readBool();
                settings->muteUnits                 = rb.readBool();

                settings->GunShotWavFilePath    = rb.readBytePtr();
                settings->VisorUsageFilePath    = rb.readBytePtr();
                settings->BackgroundWavFilePath = rb.readBytePtr();

                settings->TimeLockMessage       = rb.readBytePtr();
                settings->TimeLockFrom          = rb.readBytePtr();
                settings->TimeLockTo            = rb.readBytePtr();
                settings->inputFilePath         = rb.readBytePtr();
                settings->outputFilePath        = rb.readBytePtr();
                settings->EMPDamage             = (short)rb.readShort();
                settings->result                = rb.readInt();
                settings->preferredUnitSettings = rb.readBytePtr();
                settings->ignoreArmors          = rb.readBytePtr();

                settings->mapName       = rb.readBytePtr();
                settings->description   = rb.readBytePtr();
                settings->objectives    = rb.readBytePtr();
                settings->useObjectives = rb.readBool();

                Marshal.FreeHGlobal(ptr);
            }
        }