using System; using System.Collections.Generic; using System.Linq; using System.Text; using RomCheater.PluginFramework.Core; using System.IO; using System.Diagnostics; using RomCheater.Logging; namespace RomCheater.CorePlugins.Config { public sealed class PCSX2Config : ConfigPlugin { #region Configuration Memvers const string PCXS2_PROCESS_MAGIC = "pcsx2"; const string PCXS2_LOOKUP_MAGIC_001 = "pcsx2"; const string PCXS2_LOOKUP_MAGIC_002 = "compiled on"; const uint VTLB_VADDR_OFFSET_DEBUG = 0x20000000; #endregion public PCSX2Config() : base(false) { } public PCSX2Config(bool doinit) : base(doinit) { } protected override bool IsNotValidProcess(ProcContainer p) { bool isDebug = false; uint VTLB_RELEASE_OFFSET = 0; bool notvalid = !IsValidPSX2Process(p.ProcessInfo.Id, out isDebug, out VTLB_RELEASE_OFFSET); if (notvalid) { logger.VerboseDebug.WriteLine(" Not Allowing process {0} to be added because it was filterd out", p.Name); } else { logger.VerboseDebug.WriteLine(" Allowing process {0} to be added", p.Name); } return notvalid; } #region IPluginBase Members public override Guid ID { get { return new GuidGenerator(typeof(PCSX2Config).FullName).Guid; } } public override string Name { get { return "PCSX2 Configuration Plugin"; } } public override string Description { get { return "This plugin provides a configuration suitable for use with PCSX2"; } } #endregion private static bool IsValidPSX2Process(int pid, out bool isDebug, out uint VTLB_RELEASE_OFFSET) { bool isValid = false; isDebug = false; VTLB_RELEASE_OFFSET = 0; try { Process p = Process.GetProcessById(pid); string filename = p.MainModule.FileName; FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); byte[] exe_check = new byte[] { 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E }; r.BaseStream.Seek(0, SeekOrigin.Begin); byte[] data = r.ReadBytes(exe_check.Length); bool isExe = false; for (int i = 0; i < exe_check.Length; i++) { if (exe_check[i] == data[i]) { isExe = true; } else { isExe = false; } } r.Close(); if (!isExe) { logger.VerboseDebug.WriteLine(" Process: {0} is not a valid executable file", filename); isValid = false; } else { // check for valid pcsx2 exe fs = new FileStream(filename, FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); string found_string = sr.ReadToEnd(); if (found_string.ToLower().Contains(PCXS2_LOOKUP_MAGIC_001.ToLower()) && found_string.ToLower().Contains(PCXS2_LOOKUP_MAGIC_002.ToLower())) { isValid = true; logger.VerboseDebug.WriteLine(" Process: {0} found MAGIC LOOKUP {1} and {2}", filename, PCXS2_LOOKUP_MAGIC_001.ToLower(), PCXS2_LOOKUP_MAGIC_002.ToLower()); } sr.Close(); // check for debug fs = new FileStream(filename, FileMode.Open, FileAccess.Read); sr = new StreamReader(fs); found_string = sr.ReadToEnd(); // DebugBreak should only be present in debug build version(s) of pcsx2 if (found_string.ToLower().Contains("DebugBreak".ToLower())) { isDebug = true; logger.VerboseDebug.WriteLine(" Process: {0} found DebugBreak", filename); } sr.Close(); } //this.IsDebugBuild = isDebug; // run check to see if we have a later version with offset fixed at: 0x20000000 byte[] entrypoint_data = new byte[]{ 0x01, 0x80, 0x1A, 0x3C, 0x78, 0x53, 0x59, 0xFF, 0x00, 0x68, 0x19, 0x40, 0x01, 0x80, 0x1A, 0x3C, 0x7C, 0x00, 0x39, 0x33, 0x21, 0xD0, 0x59, 0x03, 0x40, 0x53, 0x5A, 0x8F, 0x01, 0x80, 0x19, 0x3C, 0x08, 0x00, 0x40, 0x03, 0x78, 0x53, 0x39, 0xDF }; //uint address = ramdumper.VTLB_VADDR_OFFSET_DEBUG; Sojaner.MemoryScanner.ProcessMemoryReader reader = new Sojaner.MemoryScanner.ProcessMemoryReader(); reader.ReadProcess = p; reader.OpenProcess(); int bytesReadSize; byte[] check_data = reader.ReadProcessMemory((IntPtr)VTLB_VADDR_OFFSET_DEBUG, (uint)entrypoint_data.Length, out bytesReadSize); isDebug = check_data.SequenceEqual(entrypoint_data); logger.Debug.WriteLine(" Process: {0} isDebug: {1}", filename, isDebug.ToString()); //List addresses = new List(); if (!isDebug) { for (int i = 0x1000; i < 0x2000;i++ ) { try { uint t = ((uint)i << 16) | 0x5000; check_data = reader.ReadProcessMemory((IntPtr)t, (uint)entrypoint_data.Length, out bytesReadSize); isValid = check_data.SequenceEqual(entrypoint_data); if (isValid) { //addresses.Add(t); VTLB_RELEASE_OFFSET = t; logger.VerboseDebug.WriteLine(" Process: {0} found release build entrypoint at 0x{1:x8}", filename, t); break; //use only the first valid value } } catch { } } } reader.CloseHandle(); return isValid; } catch (System.ComponentModel.Win32Exception) { } catch (Exception) { } return isValid; } } }