public bool Load(string file, string path, IEnumerable <ModulePatch> modulePatches) { var neFile = _fileUtility.FindFile(path, $"{file}.DLL"); var fullNeFilePath = Path.Combine(path, neFile); if (!System.IO.File.Exists(fullNeFilePath)) { _logger.Warn($"Unable to Load {neFile}"); return(false); } var fileData = System.IO.File.ReadAllBytes(fullNeFilePath); if (modulePatches != null) { foreach (var p in modulePatches) { _logger.Info($"Applying Patch: {p.Name} to Absolute Offet {p.AbsoluteOffset}"); var bytesToPatch = p.GetBytes(); Array.Copy(bytesToPatch.ToArray(), 0, fileData, p.AbsoluteOffset, bytesToPatch.Length); } } File = new NEFile(_logger, fullNeFilePath, fileData); return(true); }
public McvFile(IFileUtility fileUtility, string fileName, string path = "") { Messages = new Dictionary <int, byte[]>(); if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(path)) { path += Path.DirectorySeparatorChar; } FileName = fileUtility.FindFile(path, fileName); #if DEBUG _logger.Info($"Loading MCV File: {FileName}"); #endif FileContent = File.ReadAllBytes(Path.Combine(path, FileName)); #if DEBUG _logger.Info($"Parsing MCV File: {FileName}"); #endif Parse(); }
public bool Load(string file, string path, IEnumerable <ModulePatch> modulePatches) { var neFile = _fileUtility.FindFile(path, $"{file}.DLL"); var fullNeFilePath = Path.Combine(path, neFile); if (!System.IO.File.Exists(fullNeFilePath)) { _logger.Warn($"Unable to Load {neFile}"); return(false); } var fileData = System.IO.File.ReadAllBytes(fullNeFilePath); var fileCRC32 = BitConverter.ToString(new Crc32().ComputeHash(fileData)).Replace("-", string.Empty); //Absolute Offset Patching //We perform Absolute Patching here as this is the last stop before the data is loaded into the NE file and split into Segments if (modulePatches != null) { foreach (var p in modulePatches.Where(x => (bool)x?.Enabled && x.AbsoluteOffset > 0)) { if (string.Compare(p.CRC32, fileCRC32, StringComparison.InvariantCultureIgnoreCase) != 0) { _logger.Error($"Unable to apply patch {p.Name}: Module CRC32 Mismatch (Expected: {p.CRC32}, Actual: {fileCRC32})"); continue; } _logger.Info($"Applying Patch: {p.Name} to Absolute Offet {p.AbsoluteOffset}"); var bytesToPatch = p.GetBytes(); Array.Copy(bytesToPatch.ToArray(), 0, fileData, p.AbsoluteOffset, bytesToPatch.Length); } } File = new NEFile(_logger, fullNeFilePath, fileData); //Address Patching if (modulePatches != null) { foreach (var p in modulePatches.Where(x => (bool)x?.Enabled && x.Addresses.Count > 0)) { if (string.Compare(p.CRC32, fileCRC32, StringComparison.InvariantCultureIgnoreCase) != 0) { _logger.Error($"Unable to apply patch {p.Name}: Module CRC32 Mismatch (Expected: {p.CRC32}, Actual: {fileCRC32})"); continue; } foreach (var a in p.Addresses) { var bytesToPatch = p.GetBytes(); _logger.Info($"Applying Patch: {p.Name} to {a}"); Array.Copy(bytesToPatch.ToArray(), 0, File.SegmentTable.First(x => x.Ordinal == a.Segment).Data, a.Offset, bytesToPatch.Length); } } } return(true); }
public bool Load(string file, string path) { var neFile = _fileUtility.FindFile(path, $"{file}.DLL"); var fullNeFilePath = Path.Combine(path, neFile); if (!System.IO.File.Exists(fullNeFilePath)) { _logger.Warn($"Unable to Load {neFile}"); return(false); } File = new NEFile(_logger, fullNeFilePath); return(true); }
/// <summary> /// Constructor to load the specified Btrieve File at the given Path /// </summary> /// <param name="fileUtility"></param> /// <param name="path"></param> /// <param name="fileName"></param> public BtrieveFileProcessor(IFileUtility fileUtility, string path, string fileName) { _fileFinder = fileUtility; Keys = new Dictionary <ushort, BtrieveKey>(); AutoincrementedKeys = new Dictionary <ushort, BtrieveKey>(); if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(path)) { path += Path.DirectorySeparatorChar; } var loadedFileName = _fileFinder.FindFile(path, fileName); // hack for MUTANTS which tries to load a DATT file if (Path.GetExtension(loadedFileName).ToUpper() == ".DATT") { loadedFileName = Path.ChangeExtension(loadedFileName, ".DAT"); } // If a .DB version exists, load it over the .DAT file var dbFileName = loadedFileName.ToUpper().Replace(".DAT", ".DB"); var fullPath = Path.Combine(path, dbFileName); if (File.Exists(fullPath)) { LoadSqlite(fullPath); } else { var btrieveFile = new BtrieveFile(); btrieveFile.LoadFile(_logger, path, loadedFileName); CreateSqliteDB(fullPath, btrieveFile); } //Set Position to First Record StepFirst(); }
/// <summary> /// Constructor to load the specified Btrieve File at the given Path /// </summary> /// <param name="fileName"></param> /// <param name="path"></param> public BtrieveFileProcessor(string fileName, string path) { _fileFinder = DependencyInjection.ServiceResolver.GetService <IFileUtility>(); if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory(); } if (!path.EndsWith(Path.DirectorySeparatorChar)) { path += Path.DirectorySeparatorChar; } LoadedFilePath = path; LoadedFileName = _fileFinder.FindFile(path, fileName); //If a .EMU version exists, load it over the .DAT file var jsonFileName = LoadedFileName.ToUpper().Replace(".DAT", ".EMU"); if (File.Exists($"{LoadedFilePath}{jsonFileName}")) { LoadedFileName = jsonFileName; LoadJson(LoadedFilePath, LoadedFileName); } else { LoadBtrieve(LoadedFilePath, LoadedFileName); SaveJson(); } //Ensure loaded records (regardless of source) are in order by their offset within the Btrieve file LoadedFile.Records = LoadedFile.Records.OrderBy(x => x.Offset).ToList(); //Set Position to First Record Position = LoadedFile.Records.OrderBy(x => x.Offset).FirstOrDefault()?.Offset ?? 0; }
/// <summary> /// Constructor for MbbsModule /// /// Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module /// </summary> /// <param name="logger"></param> /// <param name="moduleIdentifier">Will be null in a test</param> /// <param name="path"></param> /// <param name="memoryCore"></param> /// <param name="fileUtility"></param> public MbbsModule(IFileUtility fileUtility, IClock clock, ILogger logger, string moduleIdentifier, string path = "", MemoryCore memoryCore = null) { _fileUtility = fileUtility; _logger = logger; _clock = clock; ModuleIdentifier = moduleIdentifier; ModuleDlls = new List <MbbsDll>(); //Sanitize and setup Path if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(path)) { path += Path.DirectorySeparatorChar; } ModulePath = path; // will be null in tests if (string.IsNullOrEmpty(ModuleIdentifier)) { Mdf = MdfFile.createForTest(); ModuleDlls.Add(new MbbsDll(fileUtility, logger) { File = NEFile.createForTest() }); } else { //Verify MDF File Exists var mdfFile = fileUtility.FindFile(ModulePath, $"{ModuleIdentifier}.MDF"); var fullMdfFilePath = Path.Combine(ModulePath, mdfFile); if (!System.IO.File.Exists(fullMdfFilePath)) { throw new FileNotFoundException($"Unable to locate Module: {fullMdfFilePath}"); } Mdf = new MdfFile(fullMdfFilePath); var moduleDll = new MbbsDll(fileUtility, logger); moduleDll.Load(Mdf.DLLFiles[0].Trim(), ModulePath); ModuleDlls.Add(moduleDll); if (Mdf.Requires.Count > 0) { foreach (var r in Mdf.Requires) { var requiredDll = new MbbsDll(fileUtility, logger); if (requiredDll.Load(r.Trim(), ModulePath)) { requiredDll.SegmentOffset = (ushort)(ModuleDlls.Sum(x => x.File.SegmentTable.Count) + 1); ModuleDlls.Add(requiredDll); } } } if (Mdf.MSGFiles.Count > 0) { Msgs = new List <MsgFile>(Mdf.MSGFiles.Count); foreach (var m in Mdf.MSGFiles) { Msgs.Add(new MsgFile(ModulePath, m)); } } } //Set Initial Values RtkickRoutines = new PointerDictionary <RealTimeRoutine>(); RtihdlrRoutines = new PointerDictionary <RealTimeRoutine>(); TaskRoutines = new PointerDictionary <RealTimeRoutine>(); TextVariables = new Dictionary <string, FarPtr>(); GlobalCommandHandlers = new List <FarPtr>(); ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(6); ExecutionUnits = new Queue <ExecutionUnit>(2); Memory = memoryCore ?? new MemoryCore(); //Declare PSP Segment var psp = new PSPStruct { NextSegOffset = 0x9FFF, EnvSeg = 0xFFFF }; Memory.AddSegment(0x4000); Memory.SetArray(0x4000, 0, psp.Data); Memory.AllocateVariable("Int21h-PSP", sizeof(ushort)); Memory.SetWord("Int21h-PSP", 0x4000); //Find _INIT_ values if any foreach (var dll in ModuleDlls) { //If it's a Test, setup a fake _INIT_ if (string.IsNullOrEmpty(ModuleIdentifier)) { dll.EntryPoints["_INIT_"] = null; return; } //Setup _INIT_ Entrypoint FarPtr initEntryPointPointer; var initResidentName = dll.File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initResidentName == null) { //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯ _logger.Warn($"({moduleIdentifier}) Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table..."); var initNonResidentName = dll.File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initNonResidentName == null) { throw new Exception("Unable to locate _INIT__ entry in Resident Name Table"); } var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } else { var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } _logger.Debug($"({ModuleIdentifier}) Located _INIT__: {initEntryPointPointer}"); dll.EntryPoints["_INIT_"] = initEntryPointPointer; } }
/// <summary> /// Constructor for MbbsModule /// /// Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module /// </summary> /// <param name="fileUtility"></param> /// <param name="clock"></param> /// <param name="logger"></param> /// <param name="moduleConfig"></param> /// <param name="memoryCore"></param> public MbbsModule(IFileUtility fileUtility, IClock clock, ILogger logger, ModuleConfiguration moduleConfig, ProtectedModeMemoryCore memoryCore = null) { _fileUtility = fileUtility; _logger = logger; _clock = clock; ModuleConfig = moduleConfig; ModuleIdentifier = moduleConfig.ModuleIdentifier; ModuleDlls = new List <MbbsDll>(); //Sanitize and setup Path if (string.IsNullOrEmpty(moduleConfig.ModulePath)) { moduleConfig.ModulePath = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(moduleConfig.ModulePath)) { moduleConfig.ModulePath += Path.DirectorySeparatorChar; } ModulePath = moduleConfig.ModulePath; // will be null in tests if (string.IsNullOrEmpty(ModuleIdentifier)) { Mdf = MdfFile.createForTest(); ModuleDlls.Add(new MbbsDll(fileUtility, logger) { File = NEFile.createForTest() }); } else { //Verify Module Path Exists if (!Directory.Exists(ModulePath)) { _logger.Error($"Unable to find the specified directory for the module {ModuleIdentifier.ToUpper()}: {ModulePath}"); _logger.Error("Please verify your Command Line Argument or the path specified in your Module JSON File and try again."); throw new DirectoryNotFoundException($"Unable to locate {ModulePath}"); } //Verify MDF File Exists var mdfFile = fileUtility.FindFile(ModulePath, $"{ModuleIdentifier}.MDF"); var fullMdfFilePath = Path.Combine(ModulePath, mdfFile); if (!File.Exists(fullMdfFilePath)) { _logger.Error($"Unable to locate {fullMdfFilePath}"); _logger.Error($"Please verify your Command Line Argument or the Module JSON File to ensure {ModuleIdentifier} is the correct Module Identifier and that the Module is installed properly."); throw new FileNotFoundException($"Unable to locate Module: {fullMdfFilePath}"); } Mdf = new MdfFile(fullMdfFilePath); LoadModuleDll(Mdf.DLLFiles[0].Trim()); if (Mdf.MSGFiles.Count > 0) { Msgs = new List <MsgFile>(Mdf.MSGFiles.Count); foreach (var m in Mdf.MSGFiles) { Msgs.Add(new MsgFile(_fileUtility, ModulePath, m)); } } } //Set Initial Values RtkickRoutines = new PointerDictionary <RealTimeRoutine>(); RtihdlrRoutines = new PointerDictionary <RealTimeRoutine>(); TaskRoutines = new PointerDictionary <RealTimeRoutine>(); GlobalCommandHandlers = new List <FarPtr>(); ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(6); ExecutionUnits = new Queue <ExecutionUnit>(2); Memory = memoryCore ?? new ProtectedModeMemoryCore(logger); ProtectedMemory = (ProtectedModeMemoryCore)Memory; //Declare PSP Segment var psp = new PSPStruct { NextSegOffset = 0x9FFF, EnvSeg = 0xFFFF }; ProtectedMemory.AddSegment(0x4000); Memory.SetArray(0x4000, 0, psp.Data); Memory.AllocateVariable("Int21h-PSP", sizeof(ushort)); Memory.SetWord("Int21h-PSP", 0x4000); //Find _INIT_ values if any foreach (var dll in ModuleDlls) { //If it's a Test, setup a fake _INIT_ if (string.IsNullOrEmpty(ModuleIdentifier)) { dll.EntryPoints["_INIT_"] = null; return; } //Setup _INIT_ Entrypoint FarPtr initEntryPointPointer; var initResidentName = dll.File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initResidentName == null) { //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯ _logger.Warn($"({moduleConfig.ModuleIdentifier}) Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table..."); var initNonResidentName = dll.File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initNonResidentName == null) { _logger.Error($"Unable to locate _INIT__ entry in Resident Name Table for {dll.File.FileName}"); continue; } var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } else { var initEntryPoint = dll.File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable); initEntryPointPointer = new FarPtr((ushort)(initEntryPoint.SegmentNumber + dll.SegmentOffset), initEntryPoint.Offset); } _logger.Debug($"({ModuleIdentifier}) Located _INIT__: {initEntryPointPointer}"); dll.EntryPoints["_INIT_"] = initEntryPointPointer; } }
/// <summary> /// Constructor for MbbsModule /// /// Pass in an empty/blank moduleIdentifier for a Unit Test/Fake Module /// </summary> /// <param name="moduleIdentifier">Will be null in a test</param> /// <param name="path"></param> /// <param name="memoryCore"></param> public MbbsModule(IFileUtility fileUtility, string moduleIdentifier, string path = "", MemoryCore memoryCore = null) { _fileUtility = fileUtility; ModuleIdentifier = moduleIdentifier; //Sanitize and setup Path if (string.IsNullOrEmpty(path)) { path = Directory.GetCurrentDirectory(); } if (!Path.EndsInDirectorySeparator(path)) { path += Path.DirectorySeparatorChar; } ModulePath = path; // will be null in tests if (string.IsNullOrEmpty(ModuleIdentifier)) { Mdf = MdfFile.createForTest(); File = NEFile.createForTest(); } else { //Verify MDF File Exists var mdfFile = fileUtility.FindFile(ModulePath, $"{ModuleIdentifier}.MDF"); var fullMdfFilePath = Path.Combine(ModulePath, mdfFile); if (!System.IO.File.Exists(fullMdfFilePath)) { throw new FileNotFoundException($"Unable to locate Module: {fullMdfFilePath}"); } Mdf = new MdfFile(fullMdfFilePath); var trimmedDll = Mdf.DLLFiles[0].Trim(); var neFile = fileUtility.FindFile(ModulePath, $"{trimmedDll}.DLL"); var fullNeFilePath = Path.Combine(ModulePath, neFile); File = new NEFile(fullNeFilePath); } if (Mdf.MSGFiles.Count > 0) { Msgs = new List <MsgFile>(Mdf.MSGFiles.Count); foreach (var m in Mdf.MSGFiles) { Msgs.Add(new MsgFile(ModulePath, m)); } } //Set Initial Values EntryPoints = new Dictionary <string, IntPtr16>(); RtkickRoutines = new PointerDictionary <RealTimeRoutine>(); RtihdlrRoutines = new PointerDictionary <RealTimeRoutine>(); TaskRoutines = new PointerDictionary <RealTimeRoutine>(); TextVariables = new Dictionary <string, IntPtr16>(); ExecutionUnits = new Queue <ExecutionUnit>(2); ExportedModuleDictionary = new Dictionary <ushort, IExportedModule>(4); GlobalCommandHandlers = new List <IntPtr16>(); Memory = memoryCore ?? new MemoryCore(); //If it's a Test, setup a fake _INIT_ if (string.IsNullOrEmpty(ModuleIdentifier)) { EntryPoints["_INIT_"] = null; return; } //Setup _INIT_ Entrypoint IntPtr16 initEntryPointPointer; var initResidentName = File.ResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initResidentName == null) { //This only happens with MajorMUD -- I have no idea why it's a special little snowflake ¯\_(ツ)_/¯ _logger.Warn("Unable to locate _INIT_ in Resident Name Table, checking Non-Resident Name Table..."); var initNonResidentName = File.NonResidentNameTable.FirstOrDefault(x => x.Name.StartsWith("_INIT__")); if (initNonResidentName == null) { throw new Exception("Unable to locate _INIT__ entry in Resident Name Table"); } var initEntryPoint = File.EntryTable.First(x => x.Ordinal == initNonResidentName.IndexIntoEntryTable); initEntryPointPointer = new IntPtr16(initEntryPoint.SegmentNumber, initEntryPoint.Offset); } else { var initEntryPoint = File.EntryTable.First(x => x.Ordinal == initResidentName.IndexIntoEntryTable); initEntryPointPointer = new IntPtr16(initEntryPoint.SegmentNumber, initEntryPoint.Offset); } _logger.Info($"Located _INIT__: {initEntryPointPointer}"); EntryPoints["_INIT_"] = initEntryPointPointer; }