Ejemplo n.º 1
0
        public static bool Locate(RuntimeProcess runtime, out IntPtr result)
        {
            var namePattern = ByteSearch.ToPattern("ff_ParseTableInfos");

            if (runtime.Search(namePattern, out var nameOffset) == false)
            {
                result = default;
                return(false);
            }
            nameOffset = nameOffset + 1;

            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x83, 0x3D }, // cmp pointer1, 0
                ByteSearch.AnyBytes(4),
                new byte[] { 0x00 },
                new byte[] { 0x75, 0x21 }, // jnz
                0x68,                      // push $
                ByteSearch.AnyBytes(2),
                new byte[] { 0x00, 0x00 },
                0x68,                                        // push "ff_ParseTableInfos"
                BitConverter.GetBytes(nameOffset.ToInt32()),
                new byte[] { 0x6A, 0x00 },                   // push 0
                new byte[] { 0x68, 0x00, 0x04, 0x00, 0x00 }, // push 0x400
                0xE8,                                        // call $
                ByteSearch.AnyBytes(4),
                new byte[] { 0x8B, 0x55, 0x1C, },            // mov edx, [ebp+0x1C]
                new byte[] { 0x83, 0xC4, 0x10 },             // add esp, 0x10
                0xA3,                                        // mov pointer2, eax
                ByteSearch.AnyBytes(4),
            };

            if (runtime.Search(codePattern, out var codeOffset) == false)
            {
                result = default;
                return(false);
            }

            var pointer1 = runtime.ReadValueU32(codeOffset + 2);

            if (pointer1 == 0)
            {
                throw new InvalidOperationException();
            }

            var pointer2 = runtime.ReadValueU32(codeOffset + 38);

            if (pointer2 == 0)
            {
                throw new InvalidOperationException();
            }

            if (pointer1 != pointer2)
            {
                throw new InvalidOperationException();
            }

            result = new IntPtr(pointer1);
            return(true);
        }
        public static bool Locate(RuntimeProcess runtime, out IntPtr result)
        {
            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x55, 0x8B, 0xEC, 0x51 },
                new byte[] { 0x8B, 0x0D },
                ByteSearch.AnyBytes(4),
                new byte[]
                {
                    0x33, 0xC0, 0x89, 0x45, 0xFC, 0x85, 0xC9, 0x74,
                    0x14, 0x8B, 0x55, 0x08, 0x8D, 0x45, 0xFC, 0x50,
                    0x52, 0x51,
                },
                new byte[] { 0xE8 },
                ByteSearch.AnyBytes(4),
                new byte[] { 0x8B, 0x45, 0xFC, 0x83, 0xC4, 0x0C, 0x8B, 0xE5, 0x5D, 0xC3 }
            };

            if (runtime.Search(codePattern, out var codeOffset) == false)
            {
                result = default;
                return(false);
            }

            var pointer = runtime.ReadValueU32(codeOffset + 6);

            if (pointer == 0)
            {
                throw new InvalidOperationException();
            }

            result = new IntPtr(pointer);
            return(true);
        }
        public void SearchDir(string path)
        {
            var search = new ByteSearch(path, LoadResults()?.Select(x => x.File));

            var charGen = new CharacterGenerator();
            var models  = charGen.GetCharacterModels(true);

            models.AddRange(charGen.GetCharacterModels(false));

            var modelPatterns = models.Select(x => (x, x.Id.ToBytes())).ToList();

            var processed = new BlockingCollection <ByteSearchResult <CharacterModel> >();

            TrackProgress(processed);

            search.Search(modelPatterns, result =>
            {
                foreach (var item in result.Results)
                {
                    Console.WriteLine($"{item.Key} -> {result.File}");
                }
                processed.Add(result);
            });

            processed.CompleteAdding();

            var results = LoadResults().Where(x => x.Found);
            var refs    = new Dictionary <Model, HashSet <string> >();

            foreach (var result in results)
            {
                foreach (var entry in result.Results)
                {
                    if (!refs.TryGetValue(entry.Key, out var files))
                    {
                        files = new HashSet <string>();
                        refs.Add(entry.Key, files);
                    }

                    var fileName = result.File.Substring(path.Length + 1).Replace("\\", "/");
                    if (fileName.EndsWith(".core"))
                    {
                        fileName = fileName.Substring(0, fileName.Length - 5);
                    }

                    files.Add(fileName);
                }
            }

            var references = refs.Select(x => new CharacterReference()
            {
                Source = x.Key.Source,
                Name   = x.Key.Name,
                Files  = x.Value.ToArray()
            });
            var json = JsonConvert.SerializeObject(references, Formatting.Indented);

            File.WriteAllText(ReferencesFile, json);
        }
Ejemplo n.º 4
0
 static string detectSoundDriver(ROMInfo info, byte[] bytes)
 {
     if (ByteSearch.contains(bytes, MP2K_SELECTSONG))
     {
         //The standard driver among most GBA games, seemingly included in the official GBA SDK (apparently). Otherwise
         //known as Sappy or M4A
         return("MP2000");
     }
     else if (ByteSearch.contains(bytes, MP2K_NEW_SELECTSONG))
     {
         //Apparently it was also recompiled at some point and some games use it (Mother 3, Minish Cap, some others) but there doesn't seem to be any consistency in terms of new games using this and older games using the allegedly older driver
         return("MP2000 (new)");
     }
     else if (ByteSearch.contains(bytes, NATSUME_MAIN))
     {
         //Not sure what uses this. Games developed by Natsume, I guess (which amounts to basically Medabots, Keitai Denju Telefang 2, Buffy the Vampire Slayer, Shaun Palmer's Pro Snowboarder, some Power Rangers and wrestling games)
         return("Natsume");
     }
     else if (ByteSearch.contains(bytes, KRAWALL_MIXCENTER))
     {
         //A third party thing that plays converted s3m/xm files, used by a few games such as
         //Lord of the Rings and The Sims according to the author's website, and also
         //Dora the Explorer: Dora's World Adventure and Harry Potter and the Prisoner of Azkaban (but
         //not the other Dora or Harry Potter games), unless I'm actually detecting this all wrong
         //and they use something else. It's possible I am because it appears in a few homebrew
         //demos (excluding the obvious Krawall Demo), but then maybe they actually do use it since it's now LGPL'd
         //so I guess I should check the credits of those?
         return("Krawall");
     }
     else if (ByteSearch.contains(bytes, RARE_AUDIO_ERROR))
     {
         //Games developed by Rare have this huge block of error text. This is probably the most wrong way to
         //possibly do this but it works and whatnot so maybe it isn't. But I feel dirty for doing this
         return("Rare");
     }
     else if (ByteSearch.contains(bytes, GAX2_INIT))
     {
         //Used by various third-party games. All of them have a block of copyright text
         //specifying that the game uses the GAX engine, and also the version which is nice, that
         //the engine is developed by Shin'en Multimedia, and also some function names like
         //GAX2_INIT a bit after that block. Although I feel like this might result in
         //false positives.... should be fine, hopefully
         return("GAX");
     }
     else if (ByteSearch.contains(bytes, LOGIK_STATE_COPYRIGHT))
     {
         //I don't know what to call this one; used in a few third party games (Asterisk & Obelisk XXL, Driv3r among others)
         //Gotta admit I don't really like this and should detect it better, but it is apparent that those two games use things by this
         //company at least
         return("GBAModPlay/LS_Play");
     }
     else
     {
         return("Unknown");
     }
 }
Ejemplo n.º 5
0
        public static bool Locate(ProcessMemory memory, out uint result)
        {
            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x55 },
                new byte[] { 0x8B, 0xEC },
                new byte[] { 0x51 },
                new byte[] { 0xA1 },
                ByteSearch.AnyBytes(4),
                new byte[] { 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00 },
                new byte[] { 0x85, 0xC0 },
                new byte[] { 0x74, 0x17 },
                new byte[] { 0x8D, 0x4D, 0xFC },
                new byte[] { 0x51 },
                new byte[] { 0xFF, 0x75, 0x08 },
                new byte[] { 0x50 },
                new byte[] { 0xE8 },
                ByteSearch.AnyBytes(4),
                new byte[] { 0x8B, 0x45, 0xFC },
                new byte[] { 0x83, 0xC4, 0x0C },
                new byte[] { 0x8B, 0xE5 },
                new byte[] { 0x5D },
                new byte[] { 0xC3 },
            };
            uint codeOffset;

            if (memory.Search(codePattern, out codeOffset) == false)
            {
                result = 0;
                return(false);
            }

            var pointer = memory.ReadU32(codeOffset + 5);

            if (pointer == 0)
            {
                throw new InvalidOperationException();
            }

            result = memory.ReadU32(pointer);
            return(true);
        }
Ejemplo n.º 6
0
        public static bool Search(this RuntimeProcess runtime, ByteSearch.Pattern pattern, out IntPtr result)
        {
            const int blockSize = 0x00A00000;
            var       data      = new byte[blockSize];
            var       address   = runtime.Process.MainModule.BaseAddress;
            var       totalSize = runtime.Process.MainModule.ModuleMemorySize;

            for (int i = 0; i < totalSize; i += blockSize - pattern.Count)
            {
                int size = Math.Min(blockSize, totalSize - i);
                runtime.Read(address + i, data, 0, size);

                int offset;
                if (ByteSearch.Match(data, 0, size, pattern, out offset) == true)
                {
                    result = address + i + offset;
                    return(true);
                }
            }
            result = default;
            return(false);
        }
Ejemplo n.º 7
0
        public static bool Locate(RuntimeProcess runtime, out IntPtr result)
        {
            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x51 },
                0xA1,
                ByteSearch.AnyBytes(4),
                new byte[] { 0xC7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00 },
                new byte[] { 0x85, 0xC0 },
                new byte[] { 0x74, 0x17 },
                new byte[] { 0x8D, 0x0C, 0x24 },
                new byte[] { 0x51 },
                new byte[] { 0xFF, 0x74, 0x24, 0x0C },
                new byte[] { 0x50 },
                0xE8,
                ByteSearch.AnyBytes(4),
                new byte[] { 0x8B, 0x44, 0x24, 0x0C },
                new byte[] { 0x83, 0xC4, 0x0C },
                new byte[] { 0x59 },
                new byte[] { 0xC3 },
            };

            if (runtime.Search(codePattern, out var codeOffset) == false)
            {
                result = default;
                return(false);
            }

            var pointer = runtime.ReadValueU32(codeOffset + 2);

            if (pointer == 0)
            {
                throw new InvalidOperationException();
            }

            result = new IntPtr(pointer);
            return(true);
        }
Ejemplo n.º 8
0
 static void detectSaveType(ROMInfo info, byte[] bytes)
 {
     if (ByteSearch.contains(bytes, EEPROM))
     {
         info.addInfo("Save type", "EEPROM");
         //Can't tell the save size from this, it's either 512 or 8192 though
     }
     else if (ByteSearch.contains(bytes, SRAM) || ByteSearch.contains(bytes, SRAM_F))
     {
         info.addInfo("Save type", "SRAM");
         info.addInfo("Save size", 32 * 1024, ROMInfo.FormatMode.SIZE);
     }
     else if (ByteSearch.contains(bytes, FLASH) || ByteSearch.contains(bytes, FLASH_512))
     {
         info.addInfo("Save type", "Flash");
         info.addInfo("Save size", 64 * 1024, ROMInfo.FormatMode.SIZE);
     }
     else if (ByteSearch.contains(bytes, FLASH_1024))
     {
         info.addInfo("Save type", "Flash");
         info.addInfo("Save size", 128 * 1024, ROMInfo.FormatMode.SIZE);
     }
 }
Ejemplo n.º 9
0
    private async void btnSearch_Click(object sender, EventArgs e)
    {
        if (btnSearch.Text == "Stop Search")
        {
            Search?.Stop();
            return;
        }

        btnSearch.Text = "Stop Search";

        CurrentSearches = tbSearch.Text.Split("\r\n", StringSplitOptions.RemoveEmptyEntries);
        lbMatches.Items.Clear();

        Search = new ByteSearch(tbDir.Text);
        try
        {
            var byteSearches = CurrentSearches.Select((x, i) => (i.ToString(), ToBytes(x))).ToList();
            await Search.SearchAsync(byteSearches, x =>
            {
                foreach (var r in x.Results)
                {
                    var text = $"{r.Key} - {x.File} - {String.Join(", ", r.Positions)}";
                    this.BeginInvoke(new Action(() =>
                    {
                        lbMatches.Items.Add(text);
                    }));
                }
            });
        }
        catch (Exception ex)
        {
            MessageBox.Show("Search Error: " + ex.Message);
        }

        Search         = null;
        btnSearch.Text = "Search";
    }
        public static bool Locate(ProcessMemory memory, out uint result)
        {
            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x55 },       // push ebp
                new byte[] { 0x8B, 0xEC }, // mov ebp, esp
                new byte[] { 0x51 },       // push ecx
                new byte[] { 0x83, 0x3D }, // cmp pointer1, 0
                ByteSearch.AnyBytes(4),
                new byte[] { 0x00 },
                new byte[] { 0x53 }, // push ebx
                new byte[] { 0x56 }, // push esi
                new byte[] { 0x57 }, // push edi
                new byte[] { 0x75 }, // jz
                ByteSearch.AnyBytes(1),
                new byte[] { 0x68 }, // push 0x000000??
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0x68 }, // push 0x????????
                ByteSearch.AnyBytes(4),
                new byte[] { 0x68 }, // push 0x000000??
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0xE8 }, // call 0x????????
                ByteSearch.AnyBytes(4),
                new byte[] { 0x68 }, // push 0x000000??
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0x68 },       // push 0x????????
                ByteSearch.AnyBytes(4),
                new byte[] { 0x6A, 0x00 }, // push 0x00
                new byte[] { 0x6A, 0x20 }, // push 0x20
                new byte[] { 0xA3 },       // mov pointer1, eax
                ByteSearch.AnyBytes(4),
                new byte[] { 0xE8 },       // call 0x????????
                ByteSearch.AnyBytes(4),
            };
            uint codeOffset;

            if (memory.Search(codePattern, out codeOffset) == false)
            {
                result = 0;
                return(false);
            }

            var pointer1 = memory.ReadU32(codeOffset + 6);

            if (pointer1 == 0)
            {
                throw new InvalidOperationException();
            }

            var pointer2 = memory.ReadU32(codeOffset + 51);

            if (pointer2 == 0)
            {
                throw new InvalidOperationException();
            }

            if (pointer1 != pointer2)
            {
                throw new InvalidOperationException();
            }

            result = memory.ReadU32(pointer1);
            return(true);
        }
Ejemplo n.º 11
0
        private static AbstractSearch CreateSearchCriterion(Type targetType, Type propertyType, string property)
        {
            AbstractSearch result = null;

            if (propertyType.IsCollectionType())
            {
                propertyType = propertyType.GetGenericArguments().First();
            }

            if (propertyType.IsEnum)
            {
                result = new EnumSearch(propertyType);
            }
            else if (propertyType == typeof(string))
            {
                result = new TextSearch();
            }
            else if (propertyType == typeof(bool) || propertyType == typeof(bool?))
            {
                result = new BooleanSearch();
            }
            else if (propertyType == typeof(byte) || propertyType == typeof(byte?))
            {
                result = new ByteSearch();
            }
            else if (propertyType == typeof(char) || propertyType == typeof(char?))
            {
                result = new CharacterSearch();
            }
            else if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
            {
                result = new DateSearch();
            }
            else if (propertyType == typeof(decimal) || propertyType == typeof(decimal?))
            {
                result = new DecimalSearch();
            }
            else if (propertyType == typeof(double) || propertyType == typeof(double?))
            {
                result = new DoubleSearch();
            }
            else if (propertyType == typeof(float) || propertyType == typeof(float?))
            {
                result = new FloatSearch();
            }
            else if (propertyType == typeof(int) || propertyType == typeof(int?))
            {
                result = new IntegerSearch();
            }
            else if (propertyType == typeof(long) || propertyType == typeof(long?))
            {
                result = new LongSearch();
            }
            else if (propertyType == typeof(sbyte) || propertyType == typeof(sbyte?))
            {
                result = new SByteSearch();
            }
            else if (propertyType == typeof(short) || propertyType == typeof(short?))
            {
                result = new ShortSearch();
            }
            else if (propertyType == typeof(uint) || propertyType == typeof(uint?))
            {
                result = new UnsignedIntegerSearch();
            }
            else if (propertyType == typeof(ulong) || propertyType == typeof(ulong?))
            {
                result = new UnsignedLongSearch();
            }
            else if (propertyType == typeof(ushort) || propertyType == typeof(ushort?))
            {
                result = new UnsignedShortSearch();
            }

            if (result != null)
            {
                result.Property       = property;
                result.TargetTypeName = targetType.AssemblyQualifiedName;
            }

            return(result);
        }
        public static bool Locate(RuntimeProcess runtime, out IntPtr result)
        {
            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x55 },       // push ebp
                new byte[] { 0x8B, 0xEC }, // mov ebp, esp
                new byte[] { 0x51 },       // push ecx
                new byte[] { 0x83, 0x3D }, // cmp pointer1, 0
                ByteSearch.AnyBytes(4),
                new byte[] { 0x00 },
                new byte[] { 0x53 }, // push ebx
                new byte[] { 0x56 }, // push esi
                new byte[] { 0x57 }, // push edi
                new byte[] { 0x75 }, // jz
                ByteSearch.AnyBytes(1),
                new byte[] { 0x68 }, // push $
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0x68 }, // push $
                ByteSearch.AnyBytes(4),
                new byte[] { 0x68 }, // push $
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0xE8 }, // call $
                ByteSearch.AnyBytes(4),
                new byte[] { 0x68 }, // push $
                ByteSearch.AnyBytes(1),
                new byte[] { 0x00, 0x00, 0x00 },
                new byte[] { 0x68 },       // push $
                ByteSearch.AnyBytes(4),
                new byte[] { 0x6A, 0x00 }, // push 0x00
                new byte[] { 0x6A, 0x20 }, // push 0x20
                new byte[] { 0xA3 },       // mov pointer1, eax
                ByteSearch.AnyBytes(4),
                new byte[] { 0xE8 },       // call $
                //ByteSearch.AnyBytes(4),
            };

            if (runtime.Search(codePattern, out var codeOffset) == false)
            {
                result = default;
                return(false);
            }

            var pointer1 = runtime.ReadValueU32(codeOffset + 6);

            if (pointer1 == 0)
            {
                throw new InvalidOperationException();
            }

            var pointer2 = runtime.ReadValueU32(codeOffset + 51);

            if (pointer2 == 0)
            {
                throw new InvalidOperationException();
            }

            if (pointer1 != pointer2)
            {
                throw new InvalidOperationException();
            }

            result = new IntPtr(pointer1);
            return(true);
        }
Ejemplo n.º 13
0
        public static bool Locate(ProcessMemory memory, out uint result)
        {
            var  namePattern = Helpers.ToPattern("ff_ParseTableInfos");
            uint nameOffset;

            if (memory.Search(namePattern, out nameOffset) == false)
            {
                result = 0;
                return(false);
            }
            nameOffset = nameOffset + 1;

            var codePattern = new ByteSearch.Pattern()
            {
                new byte[] { 0x83, 0x3D }, // cmp pointer1, 0
                ByteSearch.AnyBytes(4),
                new byte[] { 0x00 },
                new byte[] { 0x75, 0x1E }, // jnz
                0x68,                      // push 0x0000????
                ByteSearch.AnyBytes(2),
                new byte[] { 0x00, 0x00 },
                0x68,                                        // push "ff_ParseTableInfos"
                BitConverter.GetBytes(nameOffset),
                new byte[] { 0x6A, 0x00 },                   // push 0
                new byte[] { 0x68, 0x00, 0x04, 0x00, 0x00 }, // push 0x400
                0xE8,                                        // call 0x????????
                ByteSearch.AnyBytes(4),
                new byte[] { 0x83, 0xC4, 0x10 },             // add esp, 10h
                0xA3,
                ByteSearch.AnyBytes(4),                      // mov pointer2, eax
            };
            uint codeOffset;

            if (memory.Search(codePattern, out codeOffset) == false)
            {
                result = 0;
                return(false);
            }

            var pointer1 = memory.ReadU32(codeOffset + 2);

            if (pointer1 == 0)
            {
                throw new InvalidOperationException();
            }

            var pointer2 = memory.ReadU32(codeOffset + 35);

            if (pointer2 == 0)
            {
                throw new InvalidOperationException();
            }

            if (pointer1 != pointer2)
            {
                throw new InvalidOperationException();
            }

            result = memory.ReadU32(pointer1);
            return(true);
        }
Ejemplo n.º 14
0
        public override void addROMInfo(ROMInfo info, ROMFile file)
        {
            info.addInfo("Platform", name);
            WrappedInputStream f = file.stream;

            byte[] entryPoint = f.read(4);
            info.addInfo("Entry point", entryPoint, true);
            byte[] nintendoLogo = f.read(156);
            info.addInfo("Nintendo logo", nintendoLogo, true);
            info.addInfo("Nintendo logo valid?", isNintendoLogoEqual(nintendoLogo));
            //TODO: Bits 2 and 7 of nintendoLogo[0x99] enable debugging functions when set (undefined instruction exceptions are sent
            //to a user handler identified using the device type)
            //0x9b bits 0 and 1 also have some crap in them but I don't even know

            string title = f.read(12, Encoding.ASCII).TrimEnd('\0');

            info.addInfo("Internal name", title);
            string gameCode = f.read(4, Encoding.ASCII);

            info.addInfo("Product code", gameCode);
            char gameType = gameCode[0];

            info.addInfo("Type", gameType, GBA_GAME_TYPES);
            string shortTitle = gameCode.Substring(1, 2);

            info.addInfo("Short title", shortTitle);
            char country = gameCode[3];

            info.addInfo("Country", country, NintendoCommon.COUNTRIES);

            string makerCode = f.read(2, Encoding.ASCII);

            info.addInfo("Publisher", makerCode, NintendoCommon.LICENSEE_CODES);
            int fixedValue = f.read();

            info.addInfo("Fixed value", fixedValue, ROMInfo.FormatMode.HEX, true);
            info.addInfo("Fixed value valid?", fixedValue == 0x96);

            //This indicates the required hardware, should be 0 but it's possible that
            //some prototype/beta/multiboot/other weird ROMs have something else
            int mainUnitCode = f.read();

            info.addInfo("Main unit code", mainUnitCode, true);

            //If bit 7 is set, the debugging handler entry point is at 0x9fe2000 and not 0x9ffc000, normally this will be 0
            int deviceType = f.read();

            info.addInfo("Device type", deviceType, true);

            byte[] reserved = f.read(7);             //Should be all 0
            info.addInfo("Reserved", reserved, true);
            int version = f.read();

            info.addInfo("Version", version);
            int checksum = f.read();

            info.addInfo("Checksum", checksum, ROMInfo.FormatMode.HEX, true);
            int calculatedChecksum = calculateChecksum(f);

            info.addInfo("Calculated checksum", calculatedChecksum, ROMInfo.FormatMode.HEX, true);
            info.addInfo("Checksum valid?", checksum == calculatedChecksum);
            byte[] reserved2 = f.read(2);
            info.addInfo("Reserved 2", reserved2, true);

            byte[] restOfCart = f.read((int)f.Length);
            info.addInfo("Has RTC", ByteSearch.contains(restOfCart, RTC));
            detectSaveType(info, restOfCart);
            info.addInfo("Sound driver", detectSoundDriver(info, restOfCart));
        }