예제 #1
0
        /// <summary>
        ///     Executes an x86 Instruction to call the specified Library/API Ordinal with the specified arguments
        /// </summary>
        /// <param name="exportedModuleSegment"></param>
        /// <param name="apiOrdinal"></param>
        /// <param name="apiArguments"></param>
        protected void ExecuteApiTest(ushort exportedModuleSegment, ushort apiOrdinal, IEnumerable <ushort> apiArguments)
        {
            if (!mbbsEmuProtectedModeMemoryCore.HasSegment(STACK_SEGMENT))
            {
                mbbsEmuProtectedModeMemoryCore.AddSegment(STACK_SEGMENT);
            }

            if (mbbsEmuProtectedModeMemoryCore.HasSegment(CODE_SEGMENT))
            {
                mbbsEmuProtectedModeMemoryCore.RemoveSegment(CODE_SEGMENT);
            }

            var apiTestCodeSegment = new Segment
            {
                Ordinal = CODE_SEGMENT,
                //Create a new CODE Segment with a
                //simple ASM call for CALL FAR librarySegment:apiOrdinal
                Data = new byte[] { 0x9A, (byte)(apiOrdinal & 0xFF), (byte)(apiOrdinal >> 8), (byte)(exportedModuleSegment & 0xFF), (byte)(exportedModuleSegment >> 8), },
                Flag = (ushort)EnumSegmentFlags.Code
            };

            mbbsEmuProtectedModeMemoryCore.AddSegment(apiTestCodeSegment);

            mbbsEmuCpuRegisters.CS = CODE_SEGMENT;
            mbbsEmuCpuRegisters.IP = 0;

            //Push Arguments to Stack
            foreach (var a in apiArguments.Reverse())
            {
                mbbsEmuCpuCore.Push(a);
            }

            //Process Instruction, e.g. call the method
            mbbsEmuCpuCore.Tick();

            if (isCdeclOrdinal(apiOrdinal))
            {
                foreach (var a in apiArguments)
                {
                    mbbsEmuCpuCore.Pop();
                }
            }
        }
예제 #2
0
        public void EndOfSegmentString()
        {
            ushort segment    = 1;
            var    memoryCore = new ProtectedModeMemoryCore(_logger);

            memoryCore.AddSegment(segment);

            var testString       = new string('X', 5) + "\0";
            var testStringOffset = (ushort)(ushort.MaxValue - testString.Length + 1);

            (memoryCore as IMemoryCore).SetArray(1, testStringOffset, Encoding.ASCII.GetBytes(testString));

            var stringFromMemory = Encoding.ASCII.GetString((memoryCore as IMemoryCore).GetString(1, testStringOffset, stripNull: false));

            stringFromMemory.Should().Be(testString);
        }
예제 #3
0
 protected void CreateCodeSegment(InstructionList instructionList, ushort segmentOrdinal = 1)
 {
     mbbsEmuProtectedModeMemoryCore.AddSegment(segmentOrdinal, instructionList);
 }
예제 #4
0
파일: Program.cs 프로젝트: tuday2/MBBSEmu
 private void CreateCodeSegment(InstructionList instructionList, ushort segmentOrdinal = 0x1000)
 {
     protectedModeMemoryCore.AddSegment(segmentOrdinal, instructionList);
 }
예제 #5
0
        /// <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;
            }
        }