├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── codeql.yml │ ├── nuget.yml │ ├── pr.yml │ └── prerelease.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CODE_STYLE.md ├── COMPATIBILITY.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── avalonia.png ├── doc ├── BaK.png ├── cryodune_orni.png ├── cryodune_worm.png ├── function_C0B8_ghidra.png ├── functions_csv.png ├── prince_of_persia.PNG ├── spice86.seer ├── stunts.PNG ├── stunts_crash.PNG ├── stunts_loop.png ├── stunts_menu.PNG └── stunts_skid.PNG ├── jetbrainsrider.svg ├── src ├── Bufdio.Spice86 │ ├── AudioDevice.cs │ ├── Bindings │ │ └── PortAudio │ │ │ ├── Enums │ │ │ ├── PaSampleFormat.cs │ │ │ ├── PaStreamCallbackFlags.cs │ │ │ ├── PaStreamCallbackResult.cs │ │ │ └── PaStreamFlags.cs │ │ │ ├── NativeMethods.cs │ │ │ └── Structs │ │ │ ├── PaDeviceInfo.cs │ │ │ └── PaStreamParameters.cs │ ├── Bufdio.Spice86.csproj │ ├── Engines │ │ ├── AudioEngineOptions.cs │ │ ├── IAudioEngine.cs │ │ └── PortAudioEngine.cs │ ├── Exceptions │ │ ├── BufdioException.cs │ │ └── PortAudioException.cs │ ├── PortAudioLib.cs │ └── Utilities │ │ ├── Ensure.cs │ │ ├── Extensions │ │ └── PortAudioExtensions.cs │ │ ├── LibraryLoader.cs │ │ └── PlatformInfo.cs ├── Directory.Build.props ├── Directory.Packages.props ├── Spice86.Core │ ├── Backend │ │ └── Audio │ │ │ ├── AudioFormat.cs │ │ │ ├── AudioPlayer.cs │ │ │ ├── DummyAudio │ │ │ └── DummyAudioPlayer.cs │ │ │ ├── IirFilters │ │ │ ├── Biquad.cs │ │ │ ├── BiquadPoleState.cs │ │ │ ├── Cascade.cs │ │ │ ├── ComplexExtensions.cs │ │ │ ├── ComplexPair.cs │ │ │ ├── ComplexUtils.cs │ │ │ ├── DirectFormAbstract.cs │ │ │ ├── DirectFormI.cs │ │ │ ├── DirectFormII.cs │ │ │ ├── HighPass.cs │ │ │ ├── HighPassTransform.cs │ │ │ ├── HighShelf.cs │ │ │ ├── LayoutBase.cs │ │ │ ├── LowPass.cs │ │ │ ├── LowPassTransform.cs │ │ │ ├── LowShelf.cs │ │ │ ├── MathSupplement.cs │ │ │ ├── PoleZeroPair.cs │ │ │ └── RBJBase.cs │ │ │ ├── PortAudio │ │ │ ├── PortAudioPlayer.cs │ │ │ └── PortAudioPlayerFactory.cs │ │ │ └── SampleFormat.cs │ ├── CLI │ │ ├── CommandLineParser.cs │ │ └── Configuration.cs │ ├── Emulator │ │ ├── CPU │ │ │ ├── Alu.cs │ │ │ ├── Alu16.cs │ │ │ ├── Alu32.cs │ │ │ ├── Alu8.cs │ │ │ ├── CPU.cs │ │ │ ├── CfgCpu │ │ │ │ ├── Ast │ │ │ │ │ ├── Builder │ │ │ │ │ │ ├── AstBuilder.cs │ │ │ │ │ │ ├── ConstantAstBuilder.cs │ │ │ │ │ │ ├── InstructionFieldAstBuilder.cs │ │ │ │ │ │ ├── ModRmAstBuilder.cs │ │ │ │ │ │ ├── PointerAstBuilder.cs │ │ │ │ │ │ └── RegisterAstBuilder.cs │ │ │ │ │ ├── DataType.cs │ │ │ │ │ ├── IAstVisitor.cs │ │ │ │ │ ├── IVisitableAstNode.cs │ │ │ │ │ ├── Instruction │ │ │ │ │ │ ├── InstructionNode.cs │ │ │ │ │ │ ├── InstructionOperation.cs │ │ │ │ │ │ └── RepPrefix.cs │ │ │ │ │ ├── Operations │ │ │ │ │ │ ├── BinaryOperationNode.cs │ │ │ │ │ │ └── Operation.cs │ │ │ │ │ └── Value │ │ │ │ │ │ ├── AbsolutePointerNode.cs │ │ │ │ │ │ ├── Constant │ │ │ │ │ │ ├── ConstantNode.cs │ │ │ │ │ │ └── SegmentedAddressConstantNode.cs │ │ │ │ │ │ ├── RegisterNode.cs │ │ │ │ │ │ ├── SegmentRegisterNode.cs │ │ │ │ │ │ ├── SegmentedPointer.cs │ │ │ │ │ │ └── ValueNode.cs │ │ │ │ ├── CfgCpu.cs │ │ │ │ ├── ControlFlowGraph │ │ │ │ │ ├── CfgNode.cs │ │ │ │ │ ├── ICfgNode.cs │ │ │ │ │ └── NodeToString.cs │ │ │ │ ├── Exceptions │ │ │ │ │ └── UnhandledCfgDiscrepancyException.cs │ │ │ │ ├── ExecutionContextManager.cs │ │ │ │ ├── ExecutionContextReturns.cs │ │ │ │ ├── Feeder │ │ │ │ │ ├── CfgNodeFeeder.cs │ │ │ │ │ ├── CurrentInstructions.cs │ │ │ │ │ ├── DiscriminatorReducer.cs │ │ │ │ │ ├── IInstructionReplacer.cs │ │ │ │ │ ├── InstructionReplacer.cs │ │ │ │ │ ├── InstructionReplacerRegistry.cs │ │ │ │ │ ├── InstructionsFeeder.cs │ │ │ │ │ ├── MemoryInstructionMatcher.cs │ │ │ │ │ └── PreviousInstructions.cs │ │ │ │ ├── InstructionExecutor │ │ │ │ │ ├── InstructionExecutionHelper.cs │ │ │ │ │ ├── InstructionFieldValueRetriever.cs │ │ │ │ │ ├── ModRmComputer.cs │ │ │ │ │ └── ModRmExecutor.cs │ │ │ │ ├── InstructionRenderer │ │ │ │ │ ├── AstInstructionRenderer.cs │ │ │ │ │ └── RegisterRenderer.cs │ │ │ │ ├── Linker │ │ │ │ │ ├── ExecutionContext.cs │ │ │ │ │ └── NodeLinker.cs │ │ │ │ ├── ParsedInstruction │ │ │ │ │ ├── CfgInstruction.cs │ │ │ │ │ ├── Discriminator.cs │ │ │ │ │ ├── FieldWithValue.cs │ │ │ │ │ ├── IDiscriminatorPart.cs │ │ │ │ │ ├── InstructionField.cs │ │ │ │ │ ├── InstructionSuccessorType.cs │ │ │ │ │ ├── Instructions │ │ │ │ │ │ ├── Aaa.cs │ │ │ │ │ │ ├── Aad.cs │ │ │ │ │ │ ├── Aam.cs │ │ │ │ │ │ ├── Aas.cs │ │ │ │ │ │ ├── CallFarImm16.cs │ │ │ │ │ │ ├── CallNearImm.cs │ │ │ │ │ │ ├── Cbw16.cs │ │ │ │ │ │ ├── Cbw32.cs │ │ │ │ │ │ ├── CommonGrammar │ │ │ │ │ │ │ ├── EnterInstruction.cs │ │ │ │ │ │ │ ├── InstructionWithModRmAndValueField.cs │ │ │ │ │ │ │ ├── InstructionWithOffsetField.cs │ │ │ │ │ │ │ ├── InstructionWithRegisterIndex.cs │ │ │ │ │ │ │ ├── InstructionWithSegmentRegisterIndex.cs │ │ │ │ │ │ │ ├── InstructionWithSegmentRegisterIndexAndOffsetField.cs │ │ │ │ │ │ │ ├── InstructionWithSegmentedAddressField.cs │ │ │ │ │ │ │ ├── InstructionWithValueField.cs │ │ │ │ │ │ │ └── InstructionWithValueFieldAndRegisterIndex.cs │ │ │ │ │ │ ├── Cwd16.cs │ │ │ │ │ │ ├── Cwd32.cs │ │ │ │ │ │ ├── Daa.cs │ │ │ │ │ │ ├── Das.cs │ │ │ │ │ │ ├── Enter.cs │ │ │ │ │ │ ├── FlagControl.cs │ │ │ │ │ │ ├── FnInit.cs │ │ │ │ │ │ ├── Fnstcw.cs │ │ │ │ │ │ ├── Fnstsw.cs │ │ │ │ │ │ ├── Fwait.cs │ │ │ │ │ │ ├── Grp1.cs │ │ │ │ │ │ ├── Grp2.cs │ │ │ │ │ │ ├── Grp3.cs │ │ │ │ │ │ ├── Grp45RmInc.cs │ │ │ │ │ │ ├── Grp4Callback.cs │ │ │ │ │ │ ├── Grp5RmCallFar.cs │ │ │ │ │ │ ├── Grp5RmCallNear.cs │ │ │ │ │ │ ├── Grp5RmJumpFar.cs │ │ │ │ │ │ ├── Grp5RmJumpNear.cs │ │ │ │ │ │ ├── Grp5RmPush.cs │ │ │ │ │ │ ├── Hlt.cs │ │ │ │ │ │ ├── ImulImmRm.cs │ │ │ │ │ │ ├── InAccDx.cs │ │ │ │ │ │ ├── InAccImm.cs │ │ │ │ │ │ ├── IncDecReg.cs │ │ │ │ │ │ ├── Interfaces │ │ │ │ │ │ │ ├── ICfgInstruction.cs │ │ │ │ │ │ │ ├── IInstructionWithOffsetField.cs │ │ │ │ │ │ │ ├── IInstructionWithRegisterIndex.cs │ │ │ │ │ │ │ ├── IInstructionWithSegmentRegisterIndex.cs │ │ │ │ │ │ │ ├── IInstructionWithValueField.cs │ │ │ │ │ │ │ ├── IReturnInstruction.cs │ │ │ │ │ │ │ └── StringInstruction.cs │ │ │ │ │ │ ├── Interrupt.cs │ │ │ │ │ │ ├── Interrupt3.cs │ │ │ │ │ │ ├── InterruptOverflow.cs │ │ │ │ │ │ ├── Jcc.cs │ │ │ │ │ │ ├── JmpFarImm.cs │ │ │ │ │ │ ├── JmpNearImm.cs │ │ │ │ │ │ ├── Lahf.cs │ │ │ │ │ │ ├── Lea.cs │ │ │ │ │ │ ├── Leave.cs │ │ │ │ │ │ ├── Loop.cs │ │ │ │ │ │ ├── Lxs.cs │ │ │ │ │ │ ├── Mixins │ │ │ │ │ │ │ ├── Cmps.mixin │ │ │ │ │ │ │ ├── Enter.mixin │ │ │ │ │ │ │ ├── FlagControl.mixin │ │ │ │ │ │ │ ├── Grp1.mixin │ │ │ │ │ │ │ ├── Grp2RmOp.mixin │ │ │ │ │ │ │ ├── Grp2RmOpImm.mixin │ │ │ │ │ │ │ ├── Grp3DivRmAcc.mixin │ │ │ │ │ │ │ ├── Grp3MulRmAcc.mixin │ │ │ │ │ │ │ ├── Grp3NegRm.mixin │ │ │ │ │ │ │ ├── Grp3NotRm.mixin │ │ │ │ │ │ │ ├── Grp3TestRmImm.mixin │ │ │ │ │ │ │ ├── Grp45RmIncDec.mixin │ │ │ │ │ │ │ ├── Grp5RmPush.mixin │ │ │ │ │ │ │ ├── ImulImmRm.mixin │ │ │ │ │ │ │ ├── ImulRm.mixin │ │ │ │ │ │ │ ├── InAccDx.mixin │ │ │ │ │ │ │ ├── InAccImm.mixin │ │ │ │ │ │ │ ├── IncDecReg.mixin │ │ │ │ │ │ │ ├── InsDx.mixin │ │ │ │ │ │ │ ├── JccNearImm.mixin │ │ │ │ │ │ │ ├── JmpNearImm.mixin │ │ │ │ │ │ │ ├── Lea.mixin │ │ │ │ │ │ │ ├── Leave.mixin │ │ │ │ │ │ │ ├── Lods.mixin │ │ │ │ │ │ │ ├── Loop.mixin │ │ │ │ │ │ │ ├── Lxs.mixin │ │ │ │ │ │ │ ├── MovAccMoffs.mixin │ │ │ │ │ │ │ ├── MovMoffsAcc.mixin │ │ │ │ │ │ │ ├── MovRegImm.mixin │ │ │ │ │ │ │ ├── MovRegRm.mixin │ │ │ │ │ │ │ ├── MovRmImm.mixin │ │ │ │ │ │ │ ├── MovRmReg.mixin │ │ │ │ │ │ │ ├── MovRmSignExtend.mixin │ │ │ │ │ │ │ ├── MovRmSreg.mixin │ │ │ │ │ │ │ ├── MovRmZeroExtend.mixin │ │ │ │ │ │ │ ├── Movs.mixin │ │ │ │ │ │ │ ├── OpAccImm.mixin │ │ │ │ │ │ │ ├── OpRegRm.mixin │ │ │ │ │ │ │ ├── OpRmReg.mixin │ │ │ │ │ │ │ ├── OutAccDx.mixin │ │ │ │ │ │ │ ├── OutAccImm.mixin │ │ │ │ │ │ │ ├── OutsDx.mixin │ │ │ │ │ │ │ ├── PopF.mixin │ │ │ │ │ │ │ ├── PopReg.mixin │ │ │ │ │ │ │ ├── PopRm.mixin │ │ │ │ │ │ │ ├── Popa.mixin │ │ │ │ │ │ │ ├── PushImm.mixin │ │ │ │ │ │ │ ├── PushImm8SignExtended.mixin │ │ │ │ │ │ │ ├── PushReg.mixin │ │ │ │ │ │ │ ├── Pusha.mixin │ │ │ │ │ │ │ ├── Scas.mixin │ │ │ │ │ │ │ ├── SetRmcc.mixin │ │ │ │ │ │ │ ├── ShldCl.mixin │ │ │ │ │ │ │ ├── ShldImm8.mixin │ │ │ │ │ │ │ ├── Stos.mixin │ │ │ │ │ │ │ ├── XchgRegAcc.mixin │ │ │ │ │ │ │ ├── XchgRm.mixin │ │ │ │ │ │ │ └── Xlat.mixin │ │ │ │ │ │ ├── MovAccMoffs.cs │ │ │ │ │ │ ├── MovMoffsAcc.cs │ │ │ │ │ │ ├── MovRegImm.cs │ │ │ │ │ │ ├── MovRegRm.cs │ │ │ │ │ │ ├── MovRmImm.cs │ │ │ │ │ │ ├── MovRmReg.cs │ │ │ │ │ │ ├── MovRmSignExtend.cs │ │ │ │ │ │ ├── MovRmSreg.cs │ │ │ │ │ │ ├── MovRmZeroExtend.cs │ │ │ │ │ │ ├── MovSregRm16.cs │ │ │ │ │ │ ├── Nop.cs │ │ │ │ │ │ ├── OpAccImm.cs │ │ │ │ │ │ ├── OpRegRm.cs │ │ │ │ │ │ ├── OpRmReg.cs │ │ │ │ │ │ ├── OutAccDx.cs │ │ │ │ │ │ ├── OutAccImm.cs │ │ │ │ │ │ ├── PopF.cs │ │ │ │ │ │ ├── PopReg.cs │ │ │ │ │ │ ├── PopRm.cs │ │ │ │ │ │ ├── Popa.cs │ │ │ │ │ │ ├── PushF16.cs │ │ │ │ │ │ ├── PushF32.cs │ │ │ │ │ │ ├── PushImm.cs │ │ │ │ │ │ ├── PushReg.cs │ │ │ │ │ │ ├── Pusha.cs │ │ │ │ │ │ ├── RetFar.cs │ │ │ │ │ │ ├── RetFarImm.cs │ │ │ │ │ │ ├── RetInterrupt.cs │ │ │ │ │ │ ├── RetNear.cs │ │ │ │ │ │ ├── RetNearImm.cs │ │ │ │ │ │ ├── Sahf.cs │ │ │ │ │ │ ├── Salc.cs │ │ │ │ │ │ ├── SetRmcc.cs │ │ │ │ │ │ ├── Shld.cs │ │ │ │ │ │ ├── String.cs │ │ │ │ │ │ ├── XchgRegAcc.cs │ │ │ │ │ │ ├── XchgRm.cs │ │ │ │ │ │ └── Xlat.cs │ │ │ │ │ ├── ModRm │ │ │ │ │ │ ├── DisplacementType.cs │ │ │ │ │ │ ├── InstructionWithModRm.cs │ │ │ │ │ │ ├── MemoryAddressType.cs │ │ │ │ │ │ ├── MemoryOffsetType.cs │ │ │ │ │ │ ├── ModRmContext.cs │ │ │ │ │ │ ├── ModRmOffsetType.cs │ │ │ │ │ │ ├── ModRmParsingContext.cs │ │ │ │ │ │ ├── SibBase.cs │ │ │ │ │ │ ├── SibContext.cs │ │ │ │ │ │ └── SibIndex.cs │ │ │ │ │ ├── Prefix │ │ │ │ │ │ ├── AddressSize32Prefix.cs │ │ │ │ │ │ ├── InstructionPrefix.cs │ │ │ │ │ │ ├── LockPrefix.cs │ │ │ │ │ │ ├── OperandSize32Prefix.cs │ │ │ │ │ │ ├── RepPrefix.cs │ │ │ │ │ │ └── SegmentOverrideInstructionPrefix.cs │ │ │ │ │ └── SelfModifying │ │ │ │ │ │ └── SelectorNode.cs │ │ │ │ └── Parser │ │ │ │ │ ├── BaseInstructionParser.cs │ │ │ │ │ ├── FieldReader │ │ │ │ │ ├── InstructionFieldReader.cs │ │ │ │ │ ├── InstructionReader.cs │ │ │ │ │ ├── InstructionReaderAddressSource.cs │ │ │ │ │ ├── Int16FieldReader.cs │ │ │ │ │ ├── Int32FieldReader.cs │ │ │ │ │ ├── Int8AsUshortFieldReader.cs │ │ │ │ │ ├── Int8FieldReader.cs │ │ │ │ │ ├── SegmentedAddressInstructionFieldReader.cs │ │ │ │ │ ├── UInt16BigEndianFieldReader.cs │ │ │ │ │ ├── UInt16FieldReader.cs │ │ │ │ │ ├── UInt32FieldReader.cs │ │ │ │ │ └── UInt8FieldReader.cs │ │ │ │ │ ├── InstructionParser.cs │ │ │ │ │ ├── InstructionPrefixParser.cs │ │ │ │ │ ├── ModRmParser.cs │ │ │ │ │ ├── ParsingContext.cs │ │ │ │ │ └── SpecificParsers │ │ │ │ │ ├── AluOperationParser.cs │ │ │ │ │ ├── BaseGrpOperationParser.cs │ │ │ │ │ ├── Grp1Parser.cs │ │ │ │ │ ├── Grp2Parser.cs │ │ │ │ │ ├── Grp3Parser.cs │ │ │ │ │ ├── Grp45Parser.cs │ │ │ │ │ ├── InstructionWithModRmParser.cs │ │ │ │ │ ├── JccParser.cs │ │ │ │ │ ├── LoopParser.cs │ │ │ │ │ ├── Mixin │ │ │ │ │ ├── AluOperationParser.mixin │ │ │ │ │ ├── Grp1OperationParser.mixin │ │ │ │ │ ├── JccSpecificParser.mixin │ │ │ │ │ ├── OperationImmParser.mixin │ │ │ │ │ ├── OperationModRmFactory.mixin │ │ │ │ │ ├── OperationModRmImmFactory.mixin │ │ │ │ │ ├── OperationModRmImmParser.mixin │ │ │ │ │ ├── OperationModRmParser.mixin │ │ │ │ │ ├── OperationOverridableSegmentOffsetFieldParser.mixin │ │ │ │ │ ├── OperationOverridableSegmentRegisterIndexParser.mixin │ │ │ │ │ ├── OperationParser.mixin │ │ │ │ │ └── OperationRegIndexParser.mixin │ │ │ │ │ ├── MovRegImmParser.cs │ │ │ │ │ ├── OperationImmParser.cs │ │ │ │ │ ├── OperationModRmFactory.cs │ │ │ │ │ ├── OperationModRmImmParser.cs │ │ │ │ │ ├── OperationModRmParser.cs │ │ │ │ │ ├── OperationOverridableSegmentOffsetFieldParser.cs │ │ │ │ │ ├── OperationOverridableSegmentRegisterIndexParser.cs │ │ │ │ │ ├── OperationParser.cs │ │ │ │ │ ├── OperationRegIndexParser.cs │ │ │ │ │ └── SetRmccParser.cs │ │ │ ├── Exceptions │ │ │ │ ├── CpuDivisionErrorException.cs │ │ │ │ ├── CpuException.cs │ │ │ │ ├── CpuExceptionType.cs │ │ │ │ ├── CpuGeneralProtectionFaultException.cs │ │ │ │ └── CpuInvalidOpcodeException.cs │ │ │ ├── Flags.cs │ │ │ ├── IInstructionExecutor.cs │ │ │ ├── InstructionsImpl │ │ │ │ ├── Grp2CountSource.cs │ │ │ │ ├── Instructions.cs │ │ │ │ ├── Instructions16.cs │ │ │ │ ├── Instructions16Or32.cs │ │ │ │ ├── Instructions32.cs │ │ │ │ └── Instructions8.cs │ │ │ ├── InterruptVectorTable.cs │ │ │ ├── InvalidGroupIndexException.cs │ │ │ ├── InvalidModeException.cs │ │ │ ├── InvalidOpCodeException.cs │ │ │ ├── InvalidRegisterMemoryIndexException.cs │ │ │ ├── MemoryAddressMandatoryException.cs │ │ │ ├── ModRM.cs │ │ │ ├── Registers │ │ │ │ ├── GeneralRegisters.cs │ │ │ │ ├── RegisterIndex.cs │ │ │ │ ├── RegistersHolder.cs │ │ │ │ ├── RegistersIndexer.cs │ │ │ │ ├── SegmentRegisterIndex.cs │ │ │ │ ├── SegmentRegisters.cs │ │ │ │ ├── UInt16RegistersIndexer.cs │ │ │ │ ├── UInt32RegistersIndexer.cs │ │ │ │ ├── UInt8HighLowRegistersIndexer.cs │ │ │ │ ├── UInt8HighRegistersIndexer.cs │ │ │ │ └── UInt8LowRegistersIndexer.cs │ │ │ ├── Stack.cs │ │ │ └── State.cs │ │ ├── Devices │ │ │ ├── DeviceThread.cs │ │ │ ├── DirectMemoryAccess │ │ │ │ └── DmaController.cs │ │ │ ├── ExternalInput │ │ │ │ ├── DualPic.cs │ │ │ │ ├── IHardwareInterruptController.cs │ │ │ │ ├── Pic.cs │ │ │ │ └── SelectedReadRegister.cs │ │ │ ├── Input │ │ │ │ ├── Joystick │ │ │ │ │ └── Joystick.cs │ │ │ │ ├── Keyboard │ │ │ │ │ ├── Keyboard.cs │ │ │ │ │ ├── KeyboardCommand.cs │ │ │ │ │ ├── KeyboardPorts.cs │ │ │ │ │ └── KeyboardStreamedInput.cs │ │ │ │ └── Mouse │ │ │ │ │ ├── Mouse.cs │ │ │ │ │ ├── MouseEventMask.cs │ │ │ │ │ └── MouseType.cs │ │ │ ├── Sound │ │ │ │ ├── AudioEngine.cs │ │ │ │ ├── AudioPlayerFactory.cs │ │ │ │ ├── Blaster │ │ │ │ │ ├── ADPCM2.cs │ │ │ │ │ ├── ADPCM3.cs │ │ │ │ │ ├── ADPCM4.cs │ │ │ │ │ ├── ADPCMDecoder.cs │ │ │ │ │ ├── BlasterState.cs │ │ │ │ │ ├── CircularBuffer.cs │ │ │ │ │ ├── Commands.cs │ │ │ │ │ ├── CompressionLevel.cs │ │ │ │ │ ├── Dsp.cs │ │ │ │ │ ├── DspPorts.cs │ │ │ │ │ ├── DspState.cs │ │ │ │ │ ├── HardwareMixer.cs │ │ │ │ │ ├── IBlasterEnvVarProvider.cs │ │ │ │ │ ├── InterruptStatus.cs │ │ │ │ │ ├── LinearUpsampler.cs │ │ │ │ │ ├── MixerRegisters.cs │ │ │ │ │ ├── SbType.cs │ │ │ │ │ ├── SoundBlaster.cs │ │ │ │ │ └── SoundBlasterHardwareConfig.cs │ │ │ │ ├── ChannelAdapter.cs │ │ │ │ ├── GravisUltraSound.cs │ │ │ │ ├── IRequestInterrupt.cs │ │ │ │ ├── Midi │ │ │ │ │ ├── GeneralMidiDevice.cs │ │ │ │ │ ├── GeneralMidiState.cs │ │ │ │ │ ├── GeneralMidiStatus.cs │ │ │ │ │ ├── MT32 │ │ │ │ │ │ └── Mt32MidiDevice.cs │ │ │ │ │ ├── Midi.cs │ │ │ │ │ ├── MidiDevice.cs │ │ │ │ │ └── Windows │ │ │ │ │ │ └── NativeMethods.cs │ │ │ │ ├── PCSpeaker │ │ │ │ │ ├── PcSpeaker.cs │ │ │ │ │ ├── QueuedNote.cs │ │ │ │ │ └── SpeakerControl.cs │ │ │ │ ├── SoftwareMixer.cs │ │ │ │ ├── SoundChannel.cs │ │ │ │ ├── Ym7128b │ │ │ │ │ ├── ChipEngine.cs │ │ │ │ │ ├── ChipFixed.cs │ │ │ │ │ ├── ChipFixedProcessData.cs │ │ │ │ │ ├── ChipFloat.cs │ │ │ │ │ ├── ChipFloatProcessData.cs │ │ │ │ │ ├── ChipIdeal.cs │ │ │ │ │ ├── ChipIdealProcessData.cs │ │ │ │ │ ├── ChipShort.cs │ │ │ │ │ ├── ChipShortProcessData.cs │ │ │ │ │ ├── DatasheetSpecs.cs │ │ │ │ │ ├── ImplementationSpecs.cs │ │ │ │ │ ├── InputChannel.cs │ │ │ │ │ ├── OutputChannel.cs │ │ │ │ │ ├── OversamplerFixed.cs │ │ │ │ │ ├── OversamplerFloat.cs │ │ │ │ │ ├── OversamplerFloatProcess.cs │ │ │ │ │ ├── OversamplerSpecs.cs │ │ │ │ │ ├── Reg.cs │ │ │ │ │ └── YM7128B.cs │ │ │ │ └── Ymf262Emu │ │ │ │ │ ├── AdsrCalculator.cs │ │ │ │ │ ├── Channels │ │ │ │ │ ├── BassDrum.cs │ │ │ │ │ ├── Channel.cs │ │ │ │ │ ├── Channel2.cs │ │ │ │ │ ├── Channel4.cs │ │ │ │ │ ├── NullChannel.cs │ │ │ │ │ └── RhythmChannel.cs │ │ │ │ │ ├── FmSynthesizer.cs │ │ │ │ │ ├── Intrinsics.cs │ │ │ │ │ ├── OPL3FM.cs │ │ │ │ │ ├── Operators │ │ │ │ │ ├── HighHat.cs │ │ │ │ │ ├── Operator.cs │ │ │ │ │ ├── SnareDrum.cs │ │ │ │ │ └── TopCymbal.cs │ │ │ │ │ └── VibratoGenerator.cs │ │ │ ├── Timer │ │ │ │ ├── CounterActivator.cs │ │ │ │ ├── CounterConfiguratorFactory.cs │ │ │ │ ├── CyclesCounterActivator.cs │ │ │ │ ├── InvalidCounterIndexException.cs │ │ │ │ ├── Pit8254Counter.cs │ │ │ │ ├── Pit8254Register.cs │ │ │ │ ├── TimeCounterActivator.cs │ │ │ │ └── Timer.cs │ │ │ └── Video │ │ │ │ ├── ArgbPalette.cs │ │ │ │ ├── BitManipulationExtensions.cs │ │ │ │ ├── IVgaFunctionality.cs │ │ │ │ ├── IVgaRenderer.cs │ │ │ │ ├── IVideoMemory.cs │ │ │ │ ├── IVideoState.cs │ │ │ │ ├── Ports.cs │ │ │ │ ├── Registers │ │ │ │ ├── AttributeController │ │ │ │ │ ├── AttributeControllerModeRegister.cs │ │ │ │ │ ├── ColorPlaneEnableRegister.cs │ │ │ │ │ └── ColorSelectRegister.cs │ │ │ │ ├── AttributeControllerRegisters.cs │ │ │ │ ├── CrtController │ │ │ │ │ ├── CharacterCellHeightRegister.cs │ │ │ │ │ ├── CrtModeControlRegister.cs │ │ │ │ │ ├── HorizontalBlankingEndRegister.cs │ │ │ │ │ ├── HorizontalSyncEndRegister.cs │ │ │ │ │ ├── OverflowRegister.cs │ │ │ │ │ ├── PresetRowScanRegister.cs │ │ │ │ │ ├── TextCursorEndRegister.cs │ │ │ │ │ ├── TextCursorStartRegister.cs │ │ │ │ │ ├── UnderlineRowScanlineRegister.cs │ │ │ │ │ └── VerticalSyncEndRegister.cs │ │ │ │ ├── CrtControllerRegisters.cs │ │ │ │ ├── DacRegisters.cs │ │ │ │ ├── Enums │ │ │ │ │ ├── AttributeControllerRegister.cs │ │ │ │ │ ├── CrtControllerRegister.cs │ │ │ │ │ ├── GraphicsControllerRegister.cs │ │ │ │ │ └── SequencerRegister.cs │ │ │ │ ├── General │ │ │ │ │ ├── InputStatusRegister0.cs │ │ │ │ │ ├── InputStatusRegister1.cs │ │ │ │ │ └── MiscellaneousOutput.cs │ │ │ │ ├── GeneralRegisters.cs │ │ │ │ ├── Graphics │ │ │ │ │ ├── DataRotateRegister.cs │ │ │ │ │ ├── GraphicsModeRegister.cs │ │ │ │ │ ├── MiscellaneousGraphicsRegister.cs │ │ │ │ │ └── ReadMapSelectRegister.cs │ │ │ │ ├── GraphicsControllerRegisters.cs │ │ │ │ ├── Register8.cs │ │ │ │ ├── RegisterExtensions.cs │ │ │ │ ├── Sequencer │ │ │ │ │ ├── CharacterMapSelectRegister.cs │ │ │ │ │ ├── ClockingModeRegister.cs │ │ │ │ │ ├── MemoryModeRegister.cs │ │ │ │ │ └── ResetRegister.cs │ │ │ │ └── SequencerRegisters.cs │ │ │ │ ├── Renderer.cs │ │ │ │ ├── VgaCard.cs │ │ │ │ ├── VgaIoPortHandler.cs │ │ │ │ ├── VideoFunctionalityInfo.cs │ │ │ │ ├── VideoMemory.cs │ │ │ │ └── VideoState.cs │ │ ├── Errors │ │ │ ├── InvalidVMOperationException.cs │ │ │ └── UnhandledOperationException.cs │ │ ├── Function │ │ │ ├── ByteModificationRecord.cs │ │ │ ├── CallType.cs │ │ │ ├── CircularBuffer.cs │ │ │ ├── Dump │ │ │ │ ├── EmulatorStateSerializer.cs │ │ │ │ ├── ExecutionFlowDumper.cs │ │ │ │ ├── GhidraSymbolsDumper.cs │ │ │ │ ├── MemoryDataExporter.cs │ │ │ │ ├── RecordedDataIOHandler.cs │ │ │ │ ├── RecordedDataReader.cs │ │ │ │ └── RecorderDataWriter.cs │ │ │ ├── ExecutionFlowRecorder.cs │ │ │ ├── FunctionCall.cs │ │ │ ├── FunctionCatalogue.cs │ │ │ ├── FunctionHandler.cs │ │ │ ├── FunctionInformation.cs │ │ │ ├── FunctionReturn.cs │ │ │ ├── IFunctionHandlerProvider.cs │ │ │ └── IOverrideSupplier.cs │ │ ├── Gdb │ │ │ ├── GdbCommandBreakPointHandler.cs │ │ │ ├── GdbCommandHandler.cs │ │ │ ├── GdbCommandMemoryHandler.cs │ │ │ ├── GdbCommandRegisterHandler.cs │ │ │ ├── GdbCustomCommandsHandler.cs │ │ │ ├── GdbFormatter.cs │ │ │ ├── GdbIo.cs │ │ │ └── GdbServer.cs │ │ ├── IOPorts │ │ │ ├── DefaultIOPortHandler.cs │ │ │ ├── IIOPortHandler.cs │ │ │ ├── IOPortDispatcher.cs │ │ │ └── UnhandledIOPortException.cs │ │ ├── InterruptHandlers │ │ │ ├── Bios │ │ │ │ ├── BiosEquipmentDeterminationInt11Handler.cs │ │ │ │ ├── SystemBiosInt12Handler.cs │ │ │ │ └── SystemBiosInt15Handler.cs │ │ │ ├── Common │ │ │ │ ├── Callback │ │ │ │ │ ├── Callback.cs │ │ │ │ │ ├── CallbackHandler.cs │ │ │ │ │ ├── ICallback.cs │ │ │ │ │ └── UnhandledCallbackException.cs │ │ │ │ ├── IndexBasedDispatcher │ │ │ │ │ ├── IRunnable.cs │ │ │ │ │ ├── IndexBasedDispatcher.cs │ │ │ │ │ └── RunnableAction.cs │ │ │ │ ├── MemoryWriter │ │ │ │ │ ├── InMemoryAddressSwitcher.cs │ │ │ │ │ ├── MemoryAsmWriter.cs │ │ │ │ │ └── MemoryWriter.cs │ │ │ │ └── RoutineInstall │ │ │ │ │ ├── AssemblyRoutineInstaller.cs │ │ │ │ │ ├── IAssemblyRoutineWriter.cs │ │ │ │ │ └── InterruptInstaller.cs │ │ │ ├── Dos │ │ │ │ ├── DosInt20Handler.cs │ │ │ │ ├── DosInt21Handler.cs │ │ │ │ ├── DosInt28Handler.cs │ │ │ │ ├── DosInt2fHandler.cs │ │ │ │ └── Ems │ │ │ │ │ ├── EmmHandle.cs │ │ │ │ │ ├── EmmMemory.cs │ │ │ │ │ ├── EmmPage.cs │ │ │ │ │ ├── EmmRegister.cs │ │ │ │ │ ├── EmmStatus.cs │ │ │ │ │ ├── EmmSubFunctions.cs │ │ │ │ │ └── ExpandedMemoryManager.cs │ │ │ ├── IInterruptHandler.cs │ │ │ ├── Input │ │ │ │ ├── Keyboard │ │ │ │ │ ├── BiosKeyboardBuffer.cs │ │ │ │ │ ├── BiosKeyboardInt9Handler.cs │ │ │ │ │ └── KeyboardInt16Handler.cs │ │ │ │ └── Mouse │ │ │ │ │ ├── BiosMouseInt74Handler.cs │ │ │ │ │ ├── IMouseDevice.cs │ │ │ │ │ ├── IMouseDriver.cs │ │ │ │ │ ├── MouseDriver.cs │ │ │ │ │ ├── MouseInt33Handler.cs │ │ │ │ │ ├── MouseStatus.cs │ │ │ │ │ └── MouseUserCallback.cs │ │ │ ├── InterruptHandler.cs │ │ │ ├── SystemClock │ │ │ │ └── SystemClockInt1AHandler.cs │ │ │ ├── Timer │ │ │ │ └── TimerInt8Handler.cs │ │ │ ├── UnhandledInterruptException.cs │ │ │ └── VGA │ │ │ │ ├── Data │ │ │ │ ├── Fonts.cs │ │ │ │ ├── Palettes.cs │ │ │ │ └── RegisterValueSet.cs │ │ │ │ ├── Enums │ │ │ │ ├── MemoryAction.cs │ │ │ │ ├── MemoryModel.cs │ │ │ │ ├── ModeFlags.cs │ │ │ │ └── VgaPort.cs │ │ │ │ ├── IVideoInt10Handler.cs │ │ │ │ ├── Records │ │ │ │ ├── Area.cs │ │ │ │ ├── CharacterPlusAttribute.cs │ │ │ │ ├── CursorPosition.cs │ │ │ │ ├── GraphicsOperation.cs │ │ │ │ ├── VgaMode.cs │ │ │ │ └── VideoMode.cs │ │ │ │ ├── VgaBios.cs │ │ │ │ ├── VgaConstants.cs │ │ │ │ ├── VgaFunctionality.cs │ │ │ │ ├── VgaRom.cs │ │ │ │ └── VideoModeChangedEventArgs.cs │ │ ├── LoadableFile │ │ │ ├── Bios │ │ │ │ └── BiosLoader.cs │ │ │ ├── Dos │ │ │ │ ├── Com │ │ │ │ │ └── ComLoader.cs │ │ │ │ ├── DosFileLoader.cs │ │ │ │ ├── EnvironmentBlockGenerator.cs │ │ │ │ ├── Exe │ │ │ │ │ ├── ExeFile.cs │ │ │ │ │ └── ExeLoader.cs │ │ │ │ └── PspGenerator.cs │ │ │ └── ExecutableFileLoader.cs │ │ ├── Memory │ │ │ ├── A20Gate.cs │ │ │ ├── BiosDataArea.cs │ │ │ ├── DmaChannel.cs │ │ │ ├── DmaTransferMode.cs │ │ │ ├── IDmaDevice16.cs │ │ │ ├── IDmaDevice8.cs │ │ │ ├── IMemory.cs │ │ │ ├── IMemoryDevice.cs │ │ │ ├── Indexable │ │ │ │ ├── ByteArrayBasedIndexable.cs │ │ │ │ ├── IIndexable.cs │ │ │ │ └── Indexable.cs │ │ │ ├── Indexer │ │ │ │ ├── Indexer.cs │ │ │ │ ├── Int16Indexer.cs │ │ │ │ ├── Int32ndexer.cs │ │ │ │ ├── Int8Indexer.cs │ │ │ │ ├── MemoryIndexer.cs │ │ │ │ ├── SegmentedAddressIndexer.cs │ │ │ │ ├── UInt16BigEndianIndexer.cs │ │ │ │ ├── UInt16Indexer.cs │ │ │ │ ├── UInt32Indexer.cs │ │ │ │ └── UInt8Indexer.cs │ │ │ ├── Memory.cs │ │ │ ├── MemoryMap.cs │ │ │ ├── MemoryRange.cs │ │ │ ├── Ram.cs │ │ │ └── ReaderWriter │ │ │ │ ├── ArrayReaderWriter.cs │ │ │ │ ├── ByteArrayReaderWriter.cs │ │ │ │ ├── ByteReaderWriterWithBaseAddress.cs │ │ │ │ ├── IBaseAddressProvider.cs │ │ │ │ ├── IByteReaderWriter.cs │ │ │ │ ├── IReaderWriter.cs │ │ │ │ ├── IUIntReaderWriter.cs │ │ │ │ └── UintArrayReaderWriter.cs │ │ ├── OperatingSystem │ │ │ ├── Devices │ │ │ │ ├── BlockDevice.cs │ │ │ │ ├── CharacterDevice.cs │ │ │ │ ├── ConsoleDevice.cs │ │ │ │ ├── IVirtualDevice.cs │ │ │ │ └── VirtualDeviceBase.cs │ │ │ ├── Dos.cs │ │ │ ├── DosFileManager.cs │ │ │ ├── DosMemoryManager.cs │ │ │ ├── DosPathResolver.cs │ │ │ ├── Enums │ │ │ │ ├── CountryId.cs │ │ │ │ ├── DeviceAttributes.cs │ │ │ │ ├── DosFileAttributes.cs │ │ │ │ └── ErrorCode.cs │ │ │ ├── MountedFolder.cs │ │ │ └── Structures │ │ │ │ ├── CountryInfo.cs │ │ │ │ ├── DeviceStream.cs │ │ │ │ ├── DosDiskTransferArea.cs │ │ │ │ ├── DosFileOperationResult.cs │ │ │ │ ├── DosMemoryControlBlock.cs │ │ │ │ ├── DosSwappableDataArea.cs │ │ │ │ ├── DosTables.cs │ │ │ │ ├── EnvironmentVariables.cs │ │ │ │ ├── KeyboardStream.cs │ │ │ │ ├── OpenFile.cs │ │ │ │ └── ScreenStream.cs │ │ ├── ProgramExecutor.cs │ │ ├── ReverseEngineer │ │ │ ├── ArgumentFetcher.cs │ │ │ ├── CSharpOverrideHelper.cs │ │ │ ├── DataStructure │ │ │ │ ├── AbstractMemoryBasedDataStructure.cs │ │ │ │ ├── Array │ │ │ │ │ ├── MemoryBasedArray.cs │ │ │ │ │ ├── MemoryBasedArrayEnumerator.cs │ │ │ │ │ ├── SegmentedAddressArray.cs │ │ │ │ │ ├── UInt16Array.cs │ │ │ │ │ ├── UInt32Array.cs │ │ │ │ │ └── UInt8Array.cs │ │ │ │ ├── MemoryBasedDataStructure.cs │ │ │ │ ├── MemoryBasedDataStructureWithCsBaseAddress.cs │ │ │ │ ├── MemoryBasedDataStructureWithDsBaseAddress.cs │ │ │ │ ├── MemoryBasedDataStructureWithEsBaseAddress.cs │ │ │ │ ├── MemoryBasedDataStructureWithFsBaseAddress.cs │ │ │ │ ├── MemoryBasedDataStructureWithGsBaseAddress.cs │ │ │ │ ├── MemoryBasedDataStructureWithSegmentRegisterBaseAddress.cs │ │ │ │ └── MemoryBasedDataStructureWithSsBaseAddress.cs │ │ │ └── JumpDispatcher.cs │ │ └── VM │ │ │ ├── Breakpoint │ │ │ ├── AddressBreakPoint.cs │ │ │ ├── AddressOperation.cs │ │ │ ├── AddressReadWriteBreakpoints.cs │ │ │ ├── BreakPoint.cs │ │ │ ├── BreakPointHolder.cs │ │ │ ├── BreakPointType.cs │ │ │ ├── EmulatorBreakpointsManager.cs │ │ │ └── UnconditionalBreakPoint.cs │ │ │ ├── EmulationLoop.cs │ │ │ ├── HaltRequestedException.cs │ │ │ ├── IPauseHandler.cs │ │ │ ├── Machine.cs │ │ │ └── PauseHandler.cs │ ├── GlobalSuppressions.cs │ ├── Resources │ │ ├── 2MGM.license │ │ └── 2MGM.sf2 │ └── Spice86.Core.csproj ├── Spice86.Logging │ ├── GlobalSuppressions.cs │ ├── LoggerPropertyBag.cs │ ├── LoggerService.cs │ └── Spice86.Logging.csproj ├── Spice86.MicroBenchmarkTemplate │ ├── GlobalUsings.cs │ ├── Program.cs │ └── Spice86.MicroBenchmarkTemplate.csproj ├── Spice86.Shared │ ├── Diagnostics │ │ └── PerformanceMeasurer.cs │ ├── Emulator │ │ ├── Errors │ │ │ └── UnrecoverableException.cs │ │ ├── Keyboard │ │ │ ├── Key.cs │ │ │ └── KeyboardEventArgs.cs │ │ ├── Memory │ │ │ ├── BitWidth.cs │ │ │ └── SegmentedAddress.cs │ │ ├── Mouse │ │ │ ├── MouseButton.cs │ │ │ ├── MouseButtonEventArgs.cs │ │ │ └── MouseMoveEventArgs.cs │ │ └── Video │ │ │ ├── Rgb.cs │ │ │ └── UIRenderEventArgs.cs │ ├── GlobalSuppressions.cs │ ├── Interfaces │ │ ├── IGui.cs │ │ ├── ILoggerPropertyBag.cs │ │ ├── ILoggerService.cs │ │ ├── IPerformanceMeasurer.cs │ │ ├── IScreenPresenter.cs │ │ └── ITimeMultiplier.cs │ ├── Spice86.Shared.csproj │ ├── UI │ │ └── AdditionalWindow.cs │ └── Utils │ │ ├── ConvertUtils.cs │ │ ├── DictionaryUtils.cs │ │ └── MemoryUtils.cs ├── Spice86.sln └── Spice86 │ ├── App.axaml │ ├── App.axaml.cs │ ├── Assets │ ├── ControlThemes.axaml │ ├── Debug.ico │ ├── RobotoMono-Regular.ttf │ └── Spice86.ico │ ├── Behaviors │ ├── DisassemblyScrollBehavior.cs │ ├── HighlightBehavior.cs │ ├── InstructionPointerBehavior.cs │ ├── ShowInternalDebuggerBehavior.cs │ ├── UpdateBindingOnEnterBehavior.cs │ └── UseParentListBoxContextMenuBehavior.cs │ ├── Controls │ ├── GroupBox.cs │ ├── HotKeyTabItem.cs │ ├── StatusBar.cs │ └── StatusBarItem.cs │ ├── Converters │ ├── BreakpointColorConverter.cs │ ├── ClassToTypeStringConverter.cs │ ├── ConverterUtilities.cs │ ├── FormattedTextSegmentsConverter.cs │ ├── FormatterTextKindToBrushConverter.cs │ ├── HighlightingConverter.cs │ ├── InvalidNumberToQuestionMarkConverter.cs │ ├── NullableToBooleanConverter.cs │ └── SegmentedAddressConverter.cs │ ├── DataTemplates │ └── DataTemplateProvider.cs │ ├── GlobalSuppressions.cs │ ├── Infrastructure │ ├── AvaloniaKeyScanCodeConverter.cs │ ├── DispatcherTimerStarter.cs │ ├── FilePoller.cs │ ├── HostStorageProvider.cs │ ├── StructureViewModelFactory.cs │ ├── TextClipboard.cs │ └── UIDispatcher.cs │ ├── Mappers │ └── MapperExtensions.cs │ ├── MemoryWrappers │ ├── DataMemoryDocument.cs │ ├── InstructionsDecoder.cs │ └── MemoryReadOnlyBitRangeUnion.cs │ ├── Messages │ ├── AddViewModel.cs │ ├── AddressChangedMessage.cs │ ├── RemoveViewModelMessage.cs │ └── StatusMessage.cs │ ├── Models │ └── Debugging │ │ ├── CpuFlagsInfo.cs │ │ ├── CpuStateInfo.cs │ │ ├── EnrichedInstruction.cs │ │ ├── ExceptionInfo.cs │ │ ├── FunctionInfo.cs │ │ ├── MidiInfo.cs │ │ ├── PortInfo.cs │ │ ├── SoundChannelInfo.cs │ │ └── VideoCardInfo.cs │ ├── Program.cs │ ├── Spice86.csproj │ ├── Spice86DependencyInjection.cs │ ├── Styles │ ├── DisassemblyResources.axaml │ └── Spice86.axaml │ ├── UserControls │ ├── ErrorModalDialogUserControl.axaml │ ├── ErrorModalDialogUserControl.axaml.cs │ ├── PaletteUserControl.axaml │ └── PaletteUserControl.axaml.cs │ ├── ViewLocator.cs │ ├── ViewModels │ ├── BreakpointRangeViewModel.cs │ ├── BreakpointTypeTabItemViewModel.cs │ ├── BreakpointViewModel.cs │ ├── BreakpointsViewModel.cs │ ├── CfgCpuViewModel.cs │ ├── CpuViewModel.cs │ ├── DebugWindowViewModel.cs │ ├── DebuggerLineViewModel.cs │ ├── DisassemblyViewModel.Commands.cs │ ├── DisassemblyViewModel.cs │ ├── FlagViewModel.cs │ ├── FormattedTextSegment.cs │ ├── FormattedTextSegmentsOutput.cs │ ├── IDisassemblyCommands.cs │ ├── IDisassemblyViewModel.cs │ ├── IEmulatorObjectViewModel.cs │ ├── IRegistersViewModel.cs │ ├── MainWindowViewModel.cs │ ├── MemoryViewModel.cs │ ├── MidiViewModel.cs │ ├── PaletteViewModel.cs │ ├── PerformanceViewModel.cs │ ├── RegisterViewModel.cs │ ├── RegistersViewModel.cs │ ├── SoftwareMixerViewModel.cs │ ├── StackMemoryViewModel.cs │ ├── StatusMessageViewModel.cs │ ├── StructureViewModel.cs │ ├── VideoCardViewModel.cs │ ├── ViewModelBase.cs │ └── ViewModelWithErrorDialog.cs │ ├── Views │ ├── BreakpointsView.axaml │ ├── BreakpointsView.axaml.cs │ ├── CfgCpuView.axaml │ ├── CfgCpuView.axaml.cs │ ├── CpuView.axaml │ ├── CpuView.axaml.cs │ ├── DebugWindow.axaml │ ├── DebugWindow.axaml.cs │ ├── DisassemblyView.axaml │ ├── DisassemblyView.axaml.cs │ ├── MainWindow.axaml │ ├── MainWindow.axaml.cs │ ├── MemoryView.axaml │ ├── MemoryView.axaml.cs │ ├── MidiView.axaml │ ├── MidiView.axaml.cs │ ├── PaletteView.axaml │ ├── PaletteView.axaml.cs │ ├── PerformanceView.axaml │ ├── PerformanceView.axaml.cs │ ├── RegistersView.axaml │ ├── RegistersView.axaml.cs │ ├── SoftwareMixerView.axaml │ ├── SoftwareMixerView.axaml.cs │ ├── SplashWindow.axaml │ ├── SplashWindow.axaml.cs │ ├── StatusMessageView.axaml │ ├── StatusMessageView.axaml.cs │ ├── StructureView.axaml │ ├── StructureView.axaml.cs │ ├── VideoCardView.axaml │ └── VideoCardView.axaml.cs │ ├── app.manifest │ └── libportaudio.dll └── tests ├── Directory.Packages.props └── Spice86.Tests ├── AluTests.cs ├── BreakpointTests.cs ├── CSharpOverrideHelperTest.cs ├── CfgCpu ├── CfgNodeFeederTest.cs ├── InstructionDiscriminatorTest.cs ├── InstructionsFeederTest.cs └── ModRm │ ├── ModRmExecutorTest.cs │ ├── ModRmHelper.cs │ ├── ModRmParserTest.cs │ └── TestModRmParsingContext.cs ├── CfgGraphDumper.cs ├── Devices ├── PicTests.cs └── Pit8254Tests.cs ├── Dos └── DosFileManagerTests.cs ├── GlobalSuppressions.cs ├── MachineTest.cs ├── MainMemoryTest.cs ├── MemoryBasedDataStructureTest.cs ├── Resources ├── MountPoint │ ├── drive2 │ │ └── folder │ │ │ └── test.txt │ └── foo │ │ └── bar │ │ └── C.txt ├── NativeDosTests │ ├── build.bat │ ├── c_exec.c │ ├── clean.bat │ ├── exec.asm │ ├── hello.asm │ ├── readme.md │ └── tsr.asm └── cpuTests │ ├── LICENSE │ ├── add.bin │ ├── asmsrc │ ├── add.asm │ ├── add_code.asm │ ├── bcdcnv.asm │ ├── bitwise.asm │ ├── cmpneg.asm │ ├── control.asm │ ├── datatrnf.asm │ ├── div.asm │ ├── externalint.asm │ ├── interrupt.asm │ ├── jmpmov.asm │ ├── jump1.asm │ ├── jump2.asm │ ├── mul.asm │ ├── rep.asm │ ├── rotate.asm │ ├── segpr.asm │ ├── selfmodifyinstructions.asm │ ├── selfmodifyvalue.asm │ ├── shifts.asm │ ├── strings.asm │ ├── sub.asm │ └── test386.asm │ │ ├── .gitignore │ │ ├── AUTHORS │ │ ├── COPYING │ │ ├── README.md │ │ ├── extra │ │ └── undef386.asm │ │ ├── intel-opcodes.ods │ │ ├── makefile │ │ ├── src │ │ ├── configuration.asm │ │ ├── macros_m.asm │ │ ├── print_init.asm │ │ ├── print_p.asm │ │ ├── protected_m.asm │ │ ├── protected_p.asm │ │ ├── protected_rings_p.asm │ │ ├── real_m.asm │ │ ├── test386.asm │ │ ├── tests │ │ │ ├── arith-logic_d.asm │ │ │ ├── bcd_m.asm │ │ │ ├── bit_m.asm │ │ │ ├── call_m.asm │ │ │ ├── enter_m.asm │ │ │ ├── jcc_m.asm │ │ │ ├── lea_m.asm │ │ │ ├── lea_p.asm │ │ │ ├── leave_m.asm │ │ │ ├── load_ptr_m.asm │ │ │ ├── loop_m.asm │ │ │ ├── mov_m.asm │ │ │ ├── paging_m.asm │ │ │ ├── paging_p.asm │ │ │ ├── setcc_m.asm │ │ │ ├── shift_m.asm │ │ │ ├── stack_m.asm │ │ │ ├── string_m.asm │ │ │ ├── ver_p.asm │ │ │ └── xchg_m.asm │ │ ├── tss_p.asm │ │ └── x86_e.asm │ │ └── test386-EE-reference.txt │ ├── bcdcnv.bin │ ├── bitwise.bin │ ├── cmpneg.bin │ ├── control.bin │ ├── datatrnf.bin │ ├── div.bin │ ├── externalint.bin │ ├── interrupt.bin │ ├── jmpmov.bin │ ├── jump1.bin │ ├── jump2.bin │ ├── mul.bin │ ├── rep.bin │ ├── res │ ├── DumpedListing │ │ ├── add.txt │ │ ├── bcdcnv.txt │ │ ├── bitwise.txt │ │ ├── cmpneg.txt │ │ ├── control.txt │ │ ├── datatrnf.txt │ │ ├── div.txt │ │ ├── externalint.txt │ │ ├── interrupt.txt │ │ ├── jmpmov.txt │ │ ├── jump1.txt │ │ ├── jump2.txt │ │ ├── mul.txt │ │ ├── rep.txt │ │ ├── rotate.txt │ │ ├── segpr.txt │ │ ├── selfmodifyinstructions.txt │ │ ├── selfmodifyvalue.txt │ │ ├── shifts.txt │ │ ├── strings.txt │ │ ├── sub.txt │ │ └── test386.txt │ └── MemoryDumps │ │ ├── add.bin │ │ ├── bcdcnv.bin │ │ ├── bitwise.bin │ │ ├── cmpneg.bin │ │ ├── control.bin │ │ ├── datatrnf.bin │ │ ├── div.bin │ │ ├── interrupt.bin │ │ ├── jump1.bin │ │ ├── jump2.bin │ │ ├── mul.bin │ │ ├── rep.bin │ │ ├── rotate.bin │ │ ├── segpr.bin │ │ ├── shifts.bin │ │ ├── strings.bin │ │ ├── sub.bin │ │ └── test386.bin │ ├── rotate.bin │ ├── segpr.bin │ ├── selfmodifyinstructions.bin │ ├── selfmodifyvalue.bin │ ├── shifts.bin │ ├── strings.bin │ ├── sub.bin │ └── test386.bin ├── Spice86.Tests.csproj ├── Spice86Creator.cs └── Video └── DacTest.cs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Version [e.g. 22] 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Description of Changes 2 | 3 | 4 | ### Rationale behind Changes 5 | 6 | 7 | ### Suggested Testing Steps 8 | 9 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | 3 | # Trigger the workflow on PRs 4 | on: 5 | pull_request 6 | 7 | jobs: 8 | build: 9 | 10 | strategy: 11 | matrix: 12 | os: [macos-latest, windows-latest, ubuntu-latest] 13 | fail-fast: false 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | steps: 18 | - uses: actions/checkout@v1 19 | 20 | - name: Setup .NET 21 | uses: actions/setup-dotnet@v1 22 | with: 23 | dotnet-version: '8.0.x' 24 | 25 | - name: Test with dotnet 26 | working-directory: ./src 27 | run: dotnet test --configuration Release 28 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Be nice. :) 2 | -------------------------------------------------------------------------------- /CODE_STYLE.md: -------------------------------------------------------------------------------- 1 | The code style is enforced by a .editorconfig file, inside src/ 2 | 3 | Notably, code blocks should be opened Java style: 4 | 5 | ```csharp 6 | if(blabla) { 7 | } 8 | ``` 9 | 10 | NOT C# style: 11 | 12 | ```csharp 13 | if (blabla) 14 | { 15 | } 16 | ``` 17 | 18 | Also, namespaces must be file-scoped: 19 | 20 | ```csharp 21 | namespace Spice86.Core.Emulator.blabla; 22 | ``` 23 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright: The Spice86 contributors 2 | 3 | Authors: 4 | - Kevin Ferrare 5 | - Maximilien Noal 6 | - Joris van Eijden 7 | - Artjom Vejsel 8 | - John Källén 9 | 10 | Third party authors: 11 | - Greg Divis (Aeon project: https://github.com/gregdivis/Aeon) 12 | 13 | 14 | Licensed under the Apache License, Version 2.0 (the "License"); 15 | you may not use this file except in compliance with the License. 16 | You may obtain a copy of the License at 17 | 18 | http://www.apache.org/licenses/LICENSE-2.0 19 | 20 | Unless required by applicable law or agreed to in writing, software 21 | distributed under the License is distributed on an "AS IS" BASIS, 22 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | See the License for the specific language governing permissions and 24 | limitations under the License. 25 | -------------------------------------------------------------------------------- /avalonia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/avalonia.png -------------------------------------------------------------------------------- /doc/BaK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/BaK.png -------------------------------------------------------------------------------- /doc/cryodune_orni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/cryodune_orni.png -------------------------------------------------------------------------------- /doc/cryodune_worm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/cryodune_worm.png -------------------------------------------------------------------------------- /doc/function_C0B8_ghidra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/function_C0B8_ghidra.png -------------------------------------------------------------------------------- /doc/functions_csv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/functions_csv.png -------------------------------------------------------------------------------- /doc/prince_of_persia.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/prince_of_persia.PNG -------------------------------------------------------------------------------- /doc/spice86.seer: -------------------------------------------------------------------------------- 1 | { 2 | "seerproject": { 3 | "connectmode": { 4 | "gdbserver": "127.0.0.1:10000", 5 | "targettype": "remote" 6 | }, 7 | "executable": "", 8 | "postgdbcommands": [ 9 | "" 10 | ], 11 | "pregdbcommands": [ 12 | "set architecture i8086" 13 | ], 14 | "symbolfile": "", 15 | "workingdirectory": "" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /doc/stunts.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/stunts.PNG -------------------------------------------------------------------------------- /doc/stunts_crash.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/stunts_crash.PNG -------------------------------------------------------------------------------- /doc/stunts_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/stunts_loop.png -------------------------------------------------------------------------------- /doc/stunts_menu.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/stunts_menu.PNG -------------------------------------------------------------------------------- /doc/stunts_skid.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/doc/stunts_skid.PNG -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Enums/PaSampleFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Enums; 2 | 3 | internal enum PaSampleFormat : long { 4 | paFloat32 = 0x00000001, 5 | paInt32 = 0x00000002, 6 | paInt24 = 0x00000004, 7 | paInt16 = 0x00000008, 8 | paInt8 = 0x00000010, 9 | paUInt8 = 0x00000020, 10 | paCustomFormat = 0x00010000, 11 | paNonInterleaved = 0x80000000, 12 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Enums/PaStreamCallbackFlags.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Enums; 2 | 3 | internal enum PaStreamCallbackFlags : long { 4 | paInputUnderflow = 0x00000001, 5 | paInputOverflow = 0x00000002, 6 | paOutputUnderflow = 0x00000004, 7 | paOutputOverflow = 0x00000008, 8 | paPrimingOutput = 0x00000010 9 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Enums/PaStreamCallbackResult.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Enums; 2 | 3 | internal enum PaStreamCallbackResult { 4 | paContinue = 0, 5 | paComplete = 1, 6 | paAbort = 2 7 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Enums/PaStreamFlags.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Enums; 2 | 3 | internal enum PaStreamFlags : long { 4 | paNoFlag = 0, 5 | paClipOff = 0x00000001, 6 | paDitherOff = 0x00000002, 7 | paPrimeOutputBuffersUsingStreamCallback = 0x00000008, 8 | paPlatformSpecificFlags = 0xFFFF0000 9 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Structs/PaDeviceInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Structs; 2 | 3 | using System.Runtime.InteropServices; 4 | 5 | [StructLayout(LayoutKind.Sequential)] 6 | internal readonly record struct PaDeviceInfo { 7 | public readonly int structVersion; 8 | 9 | [MarshalAs(UnmanagedType.LPStr)] 10 | public readonly string name; 11 | 12 | public readonly int hostApi; 13 | public readonly int maxInputChannels; 14 | public readonly int maxOutputChannels; 15 | public readonly double defaultLowInputLatency; 16 | public readonly double defaultLowOutputLatency; 17 | public readonly double defaultHighInputLatency; 18 | public readonly double defaultHighOutputLatency; 19 | public readonly double defaultSampleRate; 20 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bindings/PortAudio/Structs/PaStreamParameters.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Bindings.PortAudio.Structs; 2 | 3 | using Bufdio.Spice86.Bindings.PortAudio.Enums; 4 | 5 | using System; 6 | using System.Runtime.InteropServices; 7 | 8 | [StructLayout(LayoutKind.Sequential)] 9 | internal readonly record struct PaStreamParameters 10 | { 11 | public readonly int Device { get; init; } 12 | public readonly int ChannelCount { get; init; } 13 | public readonly PaSampleFormat SampleFormat { get; init; } 14 | public readonly double SuggestedLatency { get; init; } 15 | public readonly IntPtr HostApiSpecificStreamInfo { get; init; } 16 | } -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Bufdio.Spice86.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | Bufdio.Spice86 6 | Luthfi Tri Atmaja 7 | Only for Spice86 usage. A cross platform audio playback library for .NET based on PortAudio, forked from the original Bufdio by Luthfi Tri Atmaja. 8 | 9 | 10 | 11 | Bufdio.Spice86 12 | Luthfi Tri Atmaja, Kevin Ferrare, Maximilien Noal, Joris van Eijden, Artjom Vejsel 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Engines/IAudioEngine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Bufdio.Spice86.Engines; 4 | 5 | /// 6 | /// An interface to interact with the output audio device. 7 | /// Implements: . 8 | /// 9 | public interface IAudioEngine : IDisposable 10 | { 11 | /// 12 | /// Sends audio samples to the output device. 13 | /// 14 | /// Audio samples in Float32 format. 15 | void Send(Span frames); 16 | } 17 | -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Exceptions/BufdioException.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Exceptions; 2 | 3 | using System; 4 | 5 | /// 6 | /// An exception that is thrown when an error occured during Bufdio-specific operations. 7 | /// Implements: . 8 | /// 9 | public class BufdioException : Exception 10 | { 11 | /// 12 | /// Initializes . 13 | /// 14 | public BufdioException() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes by specifying exception message. 20 | /// 21 | /// A string represents exception message. 22 | public BufdioException(string message) : base(message) 23 | { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Utilities/Ensure.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Utilities; 2 | 3 | using System; 4 | using System.Diagnostics; 5 | 6 | [DebuggerStepThrough] 7 | internal static class Ensure 8 | { 9 | public static void That(bool condition, string? message = null) where TException : Exception 10 | { 11 | if (!condition) 12 | { 13 | throw string.IsNullOrWhiteSpace(message) 14 | ? Activator.CreateInstance() 15 | : (TException)Activator.CreateInstance(typeof(TException), message)!; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Bufdio.Spice86/Utilities/PlatformInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Bufdio.Spice86.Utilities; 2 | 3 | using System.Runtime.InteropServices; 4 | 5 | internal static class PlatformInfo 6 | { 7 | public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); 8 | 9 | public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); 10 | 11 | public static bool IsOSX => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); 12 | } 13 | -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/AudioFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio; 2 | 3 | /// 4 | /// Specifies an audio playback format. 5 | /// 6 | public sealed record AudioFormat(int SampleRate, int Channels, SampleFormat SampleFormat) { 7 | /// 8 | /// Gets the number of bytes per sample of the format. 9 | /// 10 | public int BytesPerSample => SampleFormat switch { 11 | SampleFormat.UnsignedPcm8 => 1, 12 | SampleFormat.SignedPcm16 => 2, 13 | SampleFormat.IeeeFloat32 => 4, 14 | _ => 0 15 | }; 16 | 17 | /// 18 | /// Gets the number of bytes per frame of the format. 19 | /// 20 | public int BytesPerFrame => BytesPerSample * Channels; 21 | } 22 | -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/DummyAudio/DummyAudioPlayer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio.DummyAudio; 2 | 3 | /// 4 | /// Dummy audio player with no backend 5 | /// 6 | sealed class DummyAudioPlayer : AudioPlayer { 7 | /// 8 | /// Initializes a new instance of the class. 9 | /// 10 | /// The audio playback format. 11 | public DummyAudioPlayer(AudioFormat format) : base(format) { 12 | } 13 | 14 | /// 15 | /// Fakes writing data to the audio device 16 | /// 17 | /// The input audio data 18 | /// The data parameter length 19 | internal override int WriteData(Span data) { 20 | // Tell we wrote it all, it's all fake anyway 21 | return data.Length; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/IirFilters/ComplexExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio.IirFilters; 2 | 3 | using System.Numerics; 4 | 5 | /// 6 | /// Extensions added to so the porting from Java was easier. 7 | /// 8 | internal static class ComplexExtensions { 9 | public static Complex Add(this Complex a, Complex b) => Complex.Add(a, b); 10 | public static Complex Multiply(this Complex a, Complex b) => Complex.Multiply(a, b); 11 | public static Complex Divide(this Complex a, Complex b) => Complex.Divide(a, b); 12 | public static Complex Subtract(this Complex a, Complex b) => Complex.Subtract(a, b); 13 | public static Complex Sqrt(this Complex a) => Complex.Sqrt(a); 14 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/IirFilters/ComplexUtils.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio.IirFilters; 2 | 3 | using System.Numerics; 4 | 5 | internal static class ComplexUtils { 6 | public static Complex PolarToComplex(double r, double theta) { 7 | if (r < 0.0) { 8 | throw new ArgumentException($"r", nameof(r)); 9 | } else { 10 | return new Complex(r * Math.Cos(theta), r * Math.Sin(theta)); 11 | } 12 | } 13 | 14 | public static Complex[] ConvertToComplex(double[] real) { 15 | var c = new Complex[real.Length]; 16 | 17 | for (int i = 0; i < real.Length; ++i) { 18 | c[i] = new Complex(real[i], 0.0); 19 | } 20 | 21 | return c; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/IirFilters/HighPass.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio.IirFilters; 2 | 3 | internal class HighPass : RbjBase { 4 | private const double Onesqrt2 = 0.707106781; 5 | 6 | public void SetupN( 7 | double cutoffFrequency, 8 | double q = Onesqrt2) { 9 | double w0 = 2 * MathSupplement.DoublePi * cutoffFrequency; 10 | double cs = Math.Cos(w0); 11 | double sn = Math.Sin(w0); 12 | double al = sn / (2 * q); 13 | double b0 = (1 + cs) / 2; 14 | double b1 = -(1 + cs); 15 | double b2 = (1 + cs) / 2; 16 | double a0 = 1 + al; 17 | double a1 = -2 * cs; 18 | double a2 = 1 - al; 19 | SetCoefficients(a0, a1, a2, b0, b1, b2); 20 | } 21 | 22 | public void Setup( 23 | double sampleRate, 24 | double cutoffFrequency, 25 | double q = Onesqrt2) { 26 | SetupN(cutoffFrequency / sampleRate, q); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/IirFilters/LowPass.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio.IirFilters; 2 | 3 | internal class LowPass : RbjBase { 4 | private const double Onesqrt2 = 0.707106781; 5 | 6 | public void SetupN( 7 | double cutoffFrequency, 8 | double q = Onesqrt2) { 9 | double w0 = 2 * MathSupplement.DoublePi * cutoffFrequency; 10 | double cs = Math.Cos(w0); 11 | double sn = Math.Sin(w0); 12 | double al = sn / (2 * q); 13 | double b0 = (1 - cs) / 2; 14 | double b1 = 1 - cs; 15 | double b2 = (1 - cs) / 2; 16 | double a0 = 1 + al; 17 | double a1 = -2 * cs; 18 | double a2 = 1 - al; 19 | SetCoefficients(a0, a1, a2, b0, b1, b2); 20 | } 21 | 22 | public void Setup( 23 | double sampleRate, 24 | double cutoffFrequency, 25 | double q = Onesqrt2) { 26 | SetupN(cutoffFrequency / sampleRate, q); 27 | } 28 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Backend/Audio/SampleFormat.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Backend.Audio; 2 | /// 3 | /// Used to specify the number of bits per sample in a sound buffer. 4 | /// 5 | public enum SampleFormat { 6 | /// 7 | /// There are eight bits per sample. 8 | /// 9 | UnsignedPcm8, 10 | /// 11 | /// There are sixteen bits per sample. 12 | /// 13 | SignedPcm16, 14 | /// 15 | /// Samples are 32-bit IEEE floating point values. 16 | /// 17 | IeeeFloat32 18 | } 19 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/DataType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | 5 | public class DataType(BitWidth bitWidth, bool signed) { 6 | public static DataType UINT8 { get; } = new(BitWidth.BYTE_8, false); 7 | public static DataType INT8 { get; } = new(BitWidth.BYTE_8, true); 8 | public static DataType UINT16 { get; } = new(BitWidth.WORD_16, false); 9 | public static DataType INT16 { get; } = new(BitWidth.WORD_16, true); 10 | public static DataType UINT32 { get; } = new(BitWidth.DWORD_32, false); 11 | public static DataType INT32 { get; } = new(BitWidth.DWORD_32, true); 12 | 13 | public BitWidth BitWidth { get; } = bitWidth; 14 | public bool Signed { get; } = signed; 15 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/IAstVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Operations; 5 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 6 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value.Constant; 7 | 8 | public interface IAstVisitor { 9 | public T VisitSegmentRegisterNode(SegmentRegisterNode node); 10 | public T VisitSegmentedPointer(SegmentedPointer node); 11 | public T VisitRegisterNode(RegisterNode node); 12 | public T VisitAbsolutePointerNode(AbsolutePointerNode node); 13 | public T VisitSegmentedAddressConstantNode(SegmentedAddressConstantNode node); 14 | public T VisitBinaryOperationNode(BinaryOperationNode node); 15 | public T VisitInstructionNode(InstructionNode node); 16 | public T VisitConstantNode(ConstantNode node); 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/IVisitableAstNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast; 2 | 3 | public interface IVisitableAstNode { 4 | public T Accept(IAstVisitor astVisitor); 5 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Instruction/InstructionNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 5 | 6 | public class InstructionNode(RepPrefix? repPrefix, InstructionOperation operation, params ValueNode[] parameters) : IVisitableAstNode { 7 | public InstructionNode(InstructionOperation operation, params ValueNode[] parameters) : this(null, operation, parameters) { 8 | } 9 | public RepPrefix? RepPrefix { get; } = repPrefix; 10 | public InstructionOperation Operation { get; } = operation; 11 | public IReadOnlyList Parameters { get; } = parameters; 12 | 13 | public virtual T Accept(IAstVisitor astVisitor) { 14 | return astVisitor.VisitInstructionNode(this); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Instruction/RepPrefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 2 | 3 | public enum RepPrefix { REP, REPE, REPNE } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Operations/BinaryOperationNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Operations; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 5 | 6 | public class BinaryOperationNode(DataType dataType, ValueNode left, Operation operation, ValueNode right) : ValueNode(dataType) { 7 | public ValueNode Left { get; } = left; 8 | public Operation Operation { get; } = operation; 9 | public ValueNode Right { get; } = right; 10 | 11 | public override T Accept(IAstVisitor astVisitor) { 12 | return astVisitor.VisitBinaryOperationNode(this); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Operations/Operation.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Operations; 2 | 3 | public enum Operation { PLUS, MULTIPLY } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/AbsolutePointerNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | 5 | public class AbsolutePointerNode(DataType dataType, ValueNode absoluteAddress) : ValueNode(dataType) { 6 | public ValueNode AbsoluteAddress { get; } = absoluteAddress; 7 | public override T Accept(IAstVisitor astVisitor) { 8 | return astVisitor.VisitAbsolutePointerNode(this); 9 | } 10 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/Constant/ConstantNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value.Constant; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public class ConstantNode(DataType dataType, uint value) : ValueNode(dataType) { 7 | public uint Value { get; } = value; 8 | public override T Accept(IAstVisitor astVisitor) { 9 | return astVisitor.VisitConstantNode(this); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/Constant/SegmentedAddressConstantNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value.Constant; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public class SegmentedAddressConstantNode(SegmentedAddress value) : ValueNode(DataType.UINT32) { 7 | public SegmentedAddress Value { get; } = value; 8 | 9 | public override T Accept(IAstVisitor astVisitor) { 10 | return astVisitor.VisitSegmentedAddressConstantNode(this); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/RegisterNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | 5 | public class RegisterNode(DataType dataType, int registerIndex) : ValueNode(dataType) { 6 | public int RegisterIndex { get; } = registerIndex; 7 | public override T Accept(IAstVisitor astVisitor) { 8 | return astVisitor.VisitRegisterNode(this); 9 | } 10 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/SegmentRegisterNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | 5 | public class SegmentRegisterNode(int registerIndex) : RegisterNode(DataType.UINT16, registerIndex) { 6 | public override T Accept(IAstVisitor astVisitor) { 7 | return astVisitor.VisitSegmentRegisterNode(this); 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/SegmentedPointer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | 5 | public class SegmentedPointer(DataType dataType, ValueNode segment, ValueNode offset) : ValueNode(dataType) { 6 | public ValueNode Segment { get; } = segment; 7 | public ValueNode Offset { get; } = offset; 8 | 9 | public override T Accept(IAstVisitor astVisitor) { 10 | return astVisitor.VisitSegmentedPointer(this); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Ast/Value/ValueNode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Ast.Value; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast; 4 | 5 | public abstract class ValueNode(DataType dataType) : IVisitableAstNode { 6 | 7 | public DataType DataType { get; } = dataType; 8 | 9 | public abstract T Accept(IAstVisitor astVisitor); 10 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Exceptions/UnhandledCfgDiscrepancyException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Exceptions; 2 | 3 | public class UnhandledCfgDiscrepancyException : Exception { 4 | public UnhandledCfgDiscrepancyException(string message) : base(message) { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Feeder/IInstructionReplacer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Feeder; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | 5 | public interface IInstructionReplacer { 6 | void ReplaceInstruction(CfgInstruction oldInstruction, CfgInstruction newInstruction); 7 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Feeder/InstructionReplacer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Feeder; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | 5 | public abstract class InstructionReplacer : IInstructionReplacer { 6 | protected InstructionReplacer(InstructionReplacerRegistry replacerRegistry) { 7 | replacerRegistry.Register(this); 8 | } 9 | public abstract void ReplaceInstruction(CfgInstruction oldInstruction, CfgInstruction newInstruction); 10 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Feeder/InstructionReplacerRegistry.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Feeder; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | 5 | public class InstructionReplacerRegistry : IInstructionReplacer { 6 | private List _replacers = new(); 7 | 8 | public void Register(InstructionReplacer replacer) { 9 | _replacers.Add(replacer); 10 | } 11 | 12 | public void ReplaceInstruction(CfgInstruction oldInstruction, CfgInstruction newInstruction) { 13 | foreach (InstructionReplacer instructionReplacer in _replacers) { 14 | instructionReplacer.ReplaceInstruction(oldInstruction, newInstruction); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Feeder/MemoryInstructionMatcher.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Feeder; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | using Spice86.Core.Emulator.Memory; 5 | 6 | using System.Linq; 7 | 8 | public class MemoryInstructionMatcher { 9 | private readonly IMemory _memory; 10 | 11 | public MemoryInstructionMatcher(IMemory memory) { 12 | this._memory = memory; 13 | } 14 | 15 | public CfgInstruction? MatchExistingInstructionWithMemory(IEnumerable instructions) { 16 | return instructions.FirstOrDefault(i => IsMatchingWithCurrentMemory(i)); 17 | } 18 | 19 | private bool IsMatchingWithCurrentMemory(CfgInstruction instruction) { 20 | Span bytesInMemory = _memory.GetSpan((int)instruction.Address.Linear, instruction.Length); 21 | return instruction.Discriminator.SpanEquivalent(bytesInMemory); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/IDiscriminatorPart.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 2 | 3 | public interface IDiscriminatorPart { 4 | /// 5 | /// Differs to value for fields which do not represent something that changes CPU logic. 6 | /// Opcode would have value and valueForDiscriminator with the same value. 7 | /// For example in MOV AX, 1234: 8 | /// - 1234 would be a InstructionField 9 | /// - value would be 1234 10 | /// - ValueForDiscriminator would be [null, null] 11 | /// 12 | public byte[] ValueForDiscriminator { get; } 13 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/InstructionSuccessorType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 2 | 3 | public enum InstructionSuccessorType { 4 | Normal, 5 | CallToReturn, 6 | CallToMisalignedReturn 7 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/CommonGrammar/EnterInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.CommonGrammar; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public abstract class EnterInstruction : CfgInstruction { 7 | public EnterInstruction(SegmentedAddress address, 8 | InstructionField opcodeField, List prefixes, 9 | InstructionField storageField, 10 | InstructionField levelField) : base(address, opcodeField, prefixes) { 11 | StorageField = storageField; 12 | LevelField = levelField; 13 | AddField(StorageField); 14 | AddField(LevelField); 15 | } 16 | public InstructionField StorageField { get; } 17 | public InstructionField LevelField { get; } 18 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/CommonGrammar/InstructionWithOffsetField.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.CommonGrammar; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | using System.Numerics; 8 | 9 | public abstract class InstructionWithOffsetField : CfgInstruction, IInstructionWithOffsetField where T : INumberBase { 10 | public InstructionWithOffsetField(SegmentedAddress address, InstructionField opcodeField, List prefixes, InstructionField offsetField) : 11 | base(address, opcodeField, prefixes) { 12 | OffsetField = offsetField; 13 | AddField(OffsetField); 14 | } 15 | 16 | public InstructionField OffsetField { get; } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/CommonGrammar/InstructionWithRegisterIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.CommonGrammar; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | public abstract class InstructionWithRegisterIndex : CfgInstruction, IInstructionWithRegisterIndex { 8 | protected InstructionWithRegisterIndex(SegmentedAddress address, 9 | InstructionField opcodeField, 10 | List prefixes, 11 | int registerIndex) : 12 | base(address, opcodeField, prefixes) { 13 | RegisterIndex = registerIndex; 14 | } 15 | public int RegisterIndex { get; } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/CommonGrammar/InstructionWithSegmentRegisterIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.CommonGrammar; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | public abstract class InstructionWithSegmentRegisterIndex: CfgInstruction, IInstructionWithSegmentRegisterIndex { 8 | protected InstructionWithSegmentRegisterIndex(SegmentedAddress address, InstructionField opcodeField, List prefixes, int segmentRegisterIndex) : base(address, opcodeField, prefixes) { 9 | SegmentRegisterIndex = segmentRegisterIndex; 10 | } 11 | 12 | public int SegmentRegisterIndex { get; } 13 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/CommonGrammar/InstructionWithSegmentedAddressField.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.CommonGrammar; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | 5 | public abstract class InstructionWithSegmentedAddressField : CfgInstruction { 6 | public InstructionWithSegmentedAddressField( 7 | SegmentedAddress address, 8 | InstructionField opcodeField, 9 | InstructionField segmentedAddressField) : 10 | base(address, opcodeField) { 11 | SegmentedAddressField = segmentedAddressField; 12 | AddField(segmentedAddressField); 13 | } 14 | 15 | public InstructionField SegmentedAddressField { get; } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Enter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Enter("SP", "ushort", "BP", 16)] 4 | public partial class Enter16; 5 | [Enter("ESP", "uint", "EBP", 32)] 6 | public partial class Enter32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/FlagControl.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [FlagControl(FlagName:"CarryFlag", FlagValue:"!helper.State.CarryFlag", "CMC")] 4 | public partial class Cmc; 5 | [FlagControl(FlagName:"CarryFlag", FlagValue:"false", "CLC")] 6 | public partial class Clc; 7 | [FlagControl(FlagName:"CarryFlag", FlagValue:"true", "STC")] 8 | public partial class Stc; 9 | [FlagControl(FlagName:"InterruptFlag", FlagValue:"false", "CLI")] 10 | public partial class Cli; 11 | [FlagControl(FlagName:"InterruptFlag", FlagValue:"true", "STI")] 12 | public partial class Sti; 13 | [FlagControl(FlagName:"DirectionFlag", FlagValue:"false", "CLD")] 14 | public partial class Cld; 15 | [FlagControl(FlagName:"DirectionFlag", FlagValue:"true", "STD")] 16 | public partial class Std; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Fwait.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Builder; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | /// 8 | /// Do nothing, this is to wait for the FPU which is not implemented 9 | /// 10 | public class Fwait : Nop { 11 | 12 | public Fwait(SegmentedAddress address, InstructionField opcodeField) : base(address, opcodeField) { 13 | } 14 | 15 | public override InstructionNode ToInstructionAst(AstBuilder builder) { 16 | return new InstructionNode(InstructionOperation.FWAIT); 17 | } 18 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Grp45RmInc.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Grp45RmIncDec("Inc", 8)] 4 | public partial class Grp45RmInc8; 5 | 6 | [Grp45RmIncDec("Inc", 16)] 7 | public partial class Grp45RmInc16; 8 | 9 | [Grp45RmIncDec("Inc", 32)] 10 | public partial class Grp45RmInc32; 11 | 12 | [Grp45RmIncDec("Dec", 8)] 13 | public partial class Grp45RmDec8; 14 | 15 | [Grp45RmIncDec("Dec", 16)] 16 | public partial class Grp45RmDec16; 17 | 18 | [Grp45RmIncDec("Dec", 32)] 19 | public partial class Grp45RmDec32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Grp5RmPush.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Grp5RmPush(16)] 4 | public partial class Grp5RmPush16; 5 | 6 | [Grp5RmPush(32)] 7 | public partial class Grp5RmPush32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Hlt.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Builder; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 5 | using Spice86.Core.Emulator.CPU.CfgCpu.InstructionExecutor; 6 | using Spice86.Shared.Emulator.Memory; 7 | 8 | public class Hlt : CfgInstruction { 9 | public Hlt(SegmentedAddress address, InstructionField opcodeField) : 10 | base(address, opcodeField) { 11 | } 12 | 13 | public override void Execute(InstructionExecutionHelper helper) { 14 | helper.State.IsRunning = false; 15 | helper.MoveIpToEndOfInstruction(this); 16 | helper.NextNode = null; 17 | } 18 | 19 | public override InstructionNode ToInstructionAst(AstBuilder builder) { 20 | return new InstructionNode(InstructionOperation.HLT); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/InAccDx.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [InAccDx("AL", 8)] 4 | public partial class InAccDx8; 5 | 6 | [InAccDx("AX", 16)] 7 | public partial class InAccDx16; 8 | 9 | [InAccDx("EAX", 32)] 10 | public partial class InAccDx32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/InAccImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [InAccImm("AL", 8)] 4 | public partial class InAccImm8; 5 | 6 | [InAccImm("AX", 16)] 7 | public partial class InAccImm16; 8 | 9 | [InAccImm("EAX", 32)] 10 | public partial class InAccImm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/IncDecReg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [IncDecReg("Inc", 16)] 4 | public partial class IncReg16; 5 | 6 | [IncDecReg("Inc", 32)] 7 | public partial class IncReg32; 8 | 9 | [IncDecReg("Dec", 16)] 10 | public partial class DecReg16; 11 | 12 | [IncDecReg("Dec", 32)] 13 | public partial class DecReg32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/ICfgInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ControlFlowGraph; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public interface ICfgInstruction : ICfgNode { 7 | /// 8 | /// Cache of Successors property per address. 9 | /// 10 | public Dictionary SuccessorsPerAddress { get; } 11 | 12 | /// 13 | /// Successors per link type 14 | /// This allows to represent the link between a call instruction and the effective return address. 15 | /// This is present for all instructions since most of them can trigger CPU faults (and interrupt calls) 16 | /// 17 | public Dictionary> SuccessorsPerType { get; } 18 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/IInstructionWithOffsetField.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | public interface IInstructionWithOffsetField { 4 | public InstructionField OffsetField { get; } 5 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/IInstructionWithRegisterIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | public interface IInstructionWithRegisterIndex { 4 | public int RegisterIndex { get; } 5 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/IInstructionWithSegmentRegisterIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | public interface IInstructionWithSegmentRegisterIndex { 4 | public int SegmentRegisterIndex { get; } 5 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/IInstructionWithValueField.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | using System.Numerics; 4 | 5 | public interface IInstructionWithValueField where T : INumberBase { 6 | public InstructionField ValueField { get; } 7 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/IReturnInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | /// 4 | /// Common interface for instructions that implement a function return 5 | /// 6 | public interface IReturnInstruction : ICfgInstruction { 7 | public CfgInstruction? CurrentCorrespondingCallInstruction { get; set; } 8 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interfaces/StringInstruction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions.Interfaces; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.InstructionExecutor; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 5 | 6 | public interface StringInstruction { 7 | public void ExecuteStringOperation(InstructionExecutionHelper helper); 8 | 9 | /// 10 | /// Whether this String instruction can modify CPU flags or not 11 | /// 12 | public bool ChangesFlags { get; } 13 | public RepPrefix? RepPrefix { get; } 14 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Interrupt3.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Builder; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 5 | using Spice86.Core.Emulator.CPU.CfgCpu.InstructionExecutor; 6 | using Spice86.Shared.Emulator.Memory; 7 | 8 | public class Interrupt3 : CfgInstruction { 9 | public Interrupt3(SegmentedAddress address, InstructionField opcodeField) : base(address, opcodeField) { 10 | } 11 | 12 | public override void Execute(InstructionExecutionHelper helper) { 13 | helper.HandleInterruptInstruction(this, 3); 14 | } 15 | 16 | public override InstructionNode ToInstructionAst(AstBuilder builder) { 17 | return new InstructionNode(InstructionOperation.INT, builder.Constant.ToNode((byte)3)); 18 | } 19 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/JmpNearImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [JmpNearImm("sbyte")] 4 | public partial class JmpNearImm8; 5 | 6 | [JmpNearImm("short")] 7 | public partial class JmpNearImm16; 8 | [JmpNearImm("int")] 9 | public partial class JmpNearImm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Lahf.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Builder; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 5 | using Spice86.Core.Emulator.CPU.CfgCpu.InstructionExecutor; 6 | using Spice86.Shared.Emulator.Memory; 7 | 8 | public class Lahf : CfgInstruction { 9 | public Lahf(SegmentedAddress address, InstructionField opcodeField) : 10 | base(address, opcodeField) { 11 | } 12 | 13 | public override void Execute(InstructionExecutionHelper helper) { 14 | helper.State.AH = (byte)helper.State.Flags.FlagRegister; 15 | helper.MoveIpAndSetNextNode(this); 16 | } 17 | 18 | public override InstructionNode ToInstructionAst(AstBuilder builder) { 19 | return new InstructionNode(InstructionOperation.LAHF); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Lea.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | [Lea(16)] 3 | public partial class Lea16; 4 | 5 | [Lea(32)] 6 | public partial class Lea32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Leave.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Leave("SP", "BP", 16)] 4 | public partial class Leave16; 5 | [Leave("ESP", "EBP", 32)] 6 | public partial class Leave32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Loop.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Loop("CX", null, "loop")] 4 | public partial class Loop16; 5 | [Loop("ECX", null, "loop")] 6 | public partial class Loop32; 7 | 8 | [Loop("CX", "helper.State.ZeroFlag", "loope")] 9 | public partial class Loopz16; 10 | [Loop("ECX", "helper.State.ZeroFlag", "loope")] 11 | public partial class Loopz32; 12 | 13 | [Loop("CX", "!helper.State.ZeroFlag", "loopne")] 14 | public partial class Loopnz16; 15 | [Loop("ECX", "!helper.State.ZeroFlag", "loopne")] 16 | public partial class Loopnz32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Lxs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Lxs(16, "ES")] 4 | public partial class Les16; 5 | [Lxs(16, "SS")] 6 | public partial class Lss16; 7 | [Lxs(16, "DS")] 8 | public partial class Lds16; 9 | [Lxs(16, "FS")] 10 | public partial class Lfs16; 11 | [Lxs(16, "GS")] 12 | public partial class Lgs16; 13 | 14 | [Lxs(32, "ES")] 15 | public partial class Les32; 16 | [Lxs(32, "SS")] 17 | public partial class Lss32; 18 | [Lxs(32, "DS")] 19 | public partial class Lds32; 20 | [Lxs(32, "FS")] 21 | public partial class Lfs32; 22 | [Lxs(32, "GS")] 23 | public partial class Lgs32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovAccMoffs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovAccMoffs("AL", 8)] 4 | public partial class MovAccMoffs8; 5 | 6 | [MovAccMoffs("AX", 16)] 7 | public partial class MovAccMoffs16; 8 | 9 | [MovAccMoffs("EAX", 32)] 10 | public partial class MovAccMoffs32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovMoffsAcc.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovMoffsAcc("AL", 8)] 4 | public partial class MovMoffsAcc8; 5 | 6 | [MovMoffsAcc("AX", 16)] 7 | public partial class MovMoffsAcc16; 8 | 9 | [MovMoffsAcc("EAX", 32)] 10 | public partial class MovMoffsAcc32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRegImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRegImm(8, "8HighLow", "byte")] 4 | public partial class MovRegImm8; 5 | 6 | [MovRegImm(16, "16", "ushort")] 7 | public partial class MovRegImm16; 8 | 9 | [MovRegImm(32, "32", "uint")] 10 | public partial class MovRegImm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRegRm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRegRm(8)] 4 | public partial class MovRegRm8; 5 | 6 | [MovRegRm(16)] 7 | public partial class MovRegRm16; 8 | 9 | [MovRegRm(32)] 10 | public partial class MovRegRm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRmImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRmImm(8, "byte")] 4 | public partial class MovRmImm8; 5 | 6 | [MovRmImm(16, "ushort")] 7 | public partial class MovRmImm16; 8 | 9 | [MovRmImm(32, "uint")] 10 | public partial class MovRmImm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRmReg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRmReg(8)] 4 | public partial class MovRmReg8; 5 | 6 | [MovRmReg(16)] 7 | public partial class MovRmReg16; 8 | 9 | [MovRmReg(32)] 10 | public partial class MovRmReg32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRmSignExtend.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRmSignExtend(DestSize: 16, SourceSize: 8, SourceSignedType: "sbyte", DestUnsignedType: "ushort")] 4 | public partial class MovRmSignExtendByte16; 5 | 6 | [MovRmSignExtend(DestSize: 32, SourceSize: 8, SourceSignedType: "sbyte", DestUnsignedType: "uint")] 7 | public partial class MovRmSignExtendByte32; 8 | 9 | [MovRmSignExtend(DestSize: 32, SourceSize: 16, SourceSignedType: "short", DestUnsignedType: "uint")] 10 | public partial class MovRmSignExtendWord32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRmSreg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRmSreg(16)] 4 | public partial class MovRmSreg16; 5 | 6 | [MovRmSreg(32)] 7 | public partial class MovRmSreg32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/MovRmZeroExtend.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [MovRmZeroExtend(DestSize: 16, SourceSize: 8)] 4 | public partial class MovRmZeroExtendByte16; 5 | 6 | [MovRmZeroExtend(DestSize: 32, SourceSize: 8)] 7 | public partial class MovRmZeroExtendByte32; 8 | 9 | [MovRmZeroExtend(DestSize: 32, SourceSize: 16)] 10 | public partial class MovRmZeroExtendWord32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Nop.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Builder; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.Ast.Instruction; 5 | using Spice86.Core.Emulator.CPU.CfgCpu.InstructionExecutor; 6 | using Spice86.Shared.Emulator.Memory; 7 | 8 | public class Nop : CfgInstruction { 9 | public Nop(SegmentedAddress address, InstructionField opcodeField) : base(address, opcodeField) { 10 | } 11 | 12 | public override void Execute(InstructionExecutionHelper helper) { 13 | // Well nothing to do :) 14 | helper.MoveIpAndSetNextNode(this); 15 | } 16 | 17 | public override InstructionNode ToInstructionAst(AstBuilder builder) { 18 | return new InstructionNode(InstructionOperation.NOP); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/OutAccDx.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [OutAccDx("AL", 8)] 4 | public partial class OutAccDx8; 5 | 6 | [OutAccDx("AX", 16)] 7 | public partial class OutAccDx16; 8 | 9 | [OutAccDx("EAX", 32)] 10 | public partial class OutAccDx32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/OutAccImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [OutAccImm("AL", 8)] 4 | public partial class OutAccImm8; 5 | 6 | [OutAccImm("AX", 16)] 7 | public partial class OutAccImm16; 8 | 9 | [OutAccImm("EAX", 32)] 10 | public partial class OutAccImm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/PopF.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [PopF(16)] 4 | public partial class PopF16; 5 | 6 | [PopF(32)] 7 | public partial class PopF32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/PopReg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [PopReg(16, false)] 4 | public partial class PopReg16; 5 | 6 | [PopReg(32, false)] 7 | public partial class PopReg32; 8 | 9 | [PopReg(16, true)] 10 | public partial class PopSReg; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/PopRm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | [PopRm(16)] 3 | public partial class PopRm16; 4 | [PopRm(32)] 5 | public partial class PopRm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Popa.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Popa(16, "")] 4 | public partial class Popa16; 5 | 6 | [Popa(32, "E")] 7 | public partial class Popa32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/PushImm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [PushImm(16, "ushort")] 4 | public partial class PushImm16; 5 | [PushImm(32, "uint")] 6 | public partial class PushImm32; 7 | 8 | [PushImm8SignExtended(16, "short", "ushort")] 9 | public partial class PushImm8SignExtended16; 10 | [PushImm8SignExtended(32, "int", "uint")] 11 | public partial class PushImm8SignExtended32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/PushReg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [PushReg(16, false)] 4 | public partial class PushReg16; 5 | 6 | [PushReg(32, false)] 7 | public partial class PushReg32; 8 | 9 | [PushReg(16, true)] 10 | public partial class PushSReg; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Pusha.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Pusha(16, "ushort", "")] 4 | public partial class Pusha16; 5 | 6 | [Pusha(32, "uint", "E")] 7 | public partial class Pusha32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Shld.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [ShldCl(16)] 4 | public partial class ShldClRm16; 5 | [ShldCl(32)] 6 | public partial class ShldClRm32; 7 | 8 | [ShldImm8(16)] 9 | public partial class ShldImm8Rm16; 10 | [ShldImm8(32)] 11 | public partial class ShldImm8Rm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/XchgRegAcc.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [XchgRegAcc(16, "AX")] 4 | public partial class XchgRegAcc16; 5 | 6 | [XchgRegAcc(32, "EAX")] 7 | public partial class XchgRegAcc32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/XchgRm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [XchgRm(8)] 4 | public partial class XchgRm8; 5 | [XchgRm(16)] 6 | public partial class XchgRm16; 7 | [XchgRm(32)] 8 | public partial class XchgRm32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Instructions/Xlat.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Instructions; 2 | 3 | [Xlat(16, "BX")] 4 | public partial class Xlat16; 5 | [Xlat(32, "EBX")] 6 | public partial class Xlat32; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/DisplacementType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum DisplacementType { 4 | ZERO, 5 | INT8, 6 | INT16, 7 | INT32 8 | } 9 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/InstructionWithModRm.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public abstract class InstructionWithModRm : CfgInstruction { 7 | public InstructionWithModRm(SegmentedAddress address, InstructionField opcodeField, List prefixes, ModRmContext modRmContext) : base(address, opcodeField, prefixes) { 8 | ModRmContext = modRmContext; 9 | AddFields(ModRmContext.FieldsInOrder); 10 | } 11 | public ModRmContext ModRmContext { get; init; } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/MemoryAddressType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum MemoryAddressType { 4 | NONE, 5 | SEGMENT_OFFSET 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/MemoryOffsetType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum MemoryOffsetType { 4 | NONE, 5 | OFFSET_PLUS_DISPLACEMENT 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/ModRmOffsetType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum ModRmOffsetType { 4 | // 16bits 5 | BX_PLUS_SI, 6 | BX_PLUS_DI, 7 | BP_PLUS_SI, 8 | BP_PLUS_DI, 9 | SI, 10 | DI, 11 | OFFSET_FIELD_16, 12 | BP, 13 | BX, 14 | //32bits 15 | EAX, 16 | ECX, 17 | EDX, 18 | EBX, 19 | SIB, 20 | EBP, 21 | ESI, 22 | EDI 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/ModRmParsingContext.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | 5 | public interface ModRmParsingContext { 6 | public BitWidth AddressWidthFromPrefixes { get; } 7 | public int? SegmentOverrideFromPrefixes { get; } 8 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/SibBase.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum SibBase { 4 | EAX, 5 | ECX, 6 | EDX, 7 | EBX, 8 | ESP, 9 | BASE_FIELD_32, 10 | EBP, 11 | ESI, 12 | EDI 13 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/ModRm/SibIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 2 | 3 | public enum SibIndex { 4 | EAX, 5 | ECX, 6 | EDX, 7 | EBX, 8 | ZERO, 9 | EBP, 10 | ESI, 11 | EDI 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Prefix/AddressSize32Prefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 2 | 3 | public class AddressSize32Prefix : InstructionPrefix { 4 | public AddressSize32Prefix(InstructionField prefixField) : base(prefixField) { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Prefix/InstructionPrefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 2 | 3 | public class InstructionPrefix { 4 | public InstructionPrefix(InstructionField prefixField) { 5 | PrefixField = prefixField; 6 | } 7 | 8 | public InstructionField PrefixField { get; } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Prefix/LockPrefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 2 | 3 | public class LockPrefix : InstructionPrefix { 4 | public LockPrefix(InstructionField prefixField) : base(prefixField) { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Prefix/OperandSize32Prefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 2 | 3 | public class OperandSize32Prefix : InstructionPrefix { 4 | public OperandSize32Prefix(InstructionField prefixField) : base(prefixField) { 5 | } 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/ParsedInstruction/Prefix/RepPrefix.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.Prefix; 2 | 3 | public class RepPrefix : InstructionPrefix { 4 | public RepPrefix(InstructionField prefixField, bool continueZeroFlagValue) : base(prefixField) { 5 | ContinueZeroFlagValue = continueZeroFlagValue; 6 | } 7 | 8 | public bool ContinueZeroFlagValue { get; } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/InstructionReaderAddressSource.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | 5 | public class InstructionReaderAddressSource { 6 | private SegmentedAddress _instructionAddress; 7 | 8 | public SegmentedAddress InstructionAddress { 9 | get => _instructionAddress; 10 | set { 11 | _instructionAddress = value; 12 | IndexInInstruction = 0; 13 | } 14 | } 15 | 16 | public int IndexInInstruction { get; set; } 17 | 18 | public SegmentedAddress CurrentAddress => new SegmentedAddress(InstructionAddress.Segment, 19 | (ushort)(InstructionAddress.Offset + IndexInInstruction)); 20 | 21 | public InstructionReaderAddressSource(SegmentedAddress instructionAddress) { 22 | _instructionAddress = instructionAddress; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/Int16FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class Int16FieldReader : InstructionFieldReader { 6 | public Int16FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 2; 12 | } 13 | 14 | public override short PeekValue() { 15 | return Memory.Int16[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/Int32FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class Int32FieldReader : InstructionFieldReader { 6 | public Int32FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 4; 12 | } 13 | 14 | public override int PeekValue() { 15 | return Memory.Int32[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/Int8AsUshortFieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | using Spice86.Core.Emulator.Memory.Indexable; 5 | 6 | public class UInt8AsUshortFieldReader : InstructionFieldReader { 7 | public UInt8AsUshortFieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 8 | base(memory, addressSource) { 9 | } 10 | 11 | public override InstructionField PeekField(bool finalValue) { 12 | if (!finalValue) { 13 | throw new ArgumentException("Can only peek final value for this type of field"); 14 | } 15 | return base.PeekField(true); 16 | } 17 | 18 | protected override int FieldSize() { 19 | return 1; 20 | } 21 | 22 | public override ushort PeekValue() { 23 | return Memory.UInt8[CurrentAddress]; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/Int8FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class Int8FieldReader : InstructionFieldReader { 6 | public Int8FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 1; 12 | } 13 | 14 | public override sbyte PeekValue() { 15 | return Memory.Int8[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/SegmentedAddressInstructionFieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | public class SegmentedAddressInstructionFieldReader : InstructionFieldReader { 7 | public SegmentedAddressInstructionFieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 8 | base(memory, addressSource) { 9 | } 10 | 11 | protected override int FieldSize() { 12 | return 4; 13 | } 14 | 15 | public override SegmentedAddress PeekValue() { 16 | return Memory.SegmentedAddress[CurrentAddress]; 17 | } 18 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/UInt16FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class UInt16FieldReader : InstructionFieldReader { 6 | public UInt16FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 2; 12 | } 13 | 14 | public override ushort PeekValue() { 15 | return Memory.UInt16[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/UInt32FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class UInt32FieldReader : InstructionFieldReader { 6 | public UInt32FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 4; 12 | } 13 | 14 | public override uint PeekValue() { 15 | return Memory.UInt32[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/FieldReader/UInt8FieldReader.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.FieldReader; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexable; 4 | 5 | public class UInt8FieldReader : InstructionFieldReader { 6 | public UInt8FieldReader(IIndexable memory, InstructionReaderAddressSource addressSource) : 7 | base(memory, addressSource) { 8 | } 9 | 10 | protected override int FieldSize() { 11 | return 1; 12 | } 13 | 14 | public override byte PeekValue() { 15 | return Memory.UInt8[CurrentAddress]; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/SpecificParsers/InstructionWithModRmParser.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.SpecificParsers; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction; 4 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | public interface IInstructionWithModRmFactory { 8 | public CfgInstruction Parse(ParsingContext context, ModRmContext modRmContext, BitWidth bitWidth); 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/SpecificParsers/OperationModRmImmParser.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.SpecificParsers; 2 | 3 | [OperationModRmImmParser(Operation: "ShldImm8Rm", Has8: false, IsOnlyField8: true, IsUnsignedField: true)] 4 | public partial class ShldImm8RmParser; 5 | 6 | [OperationModRmImmParser(Operation: "MovRmImm", Has8: true, IsOnlyField8: false, IsUnsignedField: true)] 7 | public partial class MovRmImmParser; 8 | 9 | [OperationModRmImmParser(Operation: "ImulImmRm", Has8: false, IsOnlyField8: false, IsUnsignedField: false)] 10 | public partial class ImulImmRmParser; 11 | [OperationModRmImmParser(Operation: "ImulImm8Rm", Has8: false, IsOnlyField8: true, IsUnsignedField: false)] 12 | public partial class ImulImm8RmParser; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/CfgCpu/Parser/SpecificParsers/OperationParser.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.CfgCpu.Parser.SpecificParsers; 2 | 3 | [OperationParser("Cbw", false)] 4 | partial class CbwParser; 5 | 6 | [OperationParser("Cwd", false)] 7 | partial class CwdParser; 8 | [OperationParser("PushF", false)] 9 | partial class PushFParser; 10 | [OperationParser("PopF", false)] 11 | partial class PopFParser; 12 | [OperationParser("InAccDx", true)] 13 | partial class InAccDxParser; 14 | [OperationParser("OutAccDx", true)] 15 | partial class OutAccDxParser; 16 | [OperationParser("Leave", false)] 17 | partial class LeaveParser; 18 | [OperationParser("Scas", true)] 19 | partial class ScasParser; 20 | [OperationParser("Stos", true)] 21 | partial class StosParser; 22 | [OperationParser("InsDx", true)] 23 | partial class InsDxParser; 24 | [OperationParser("Pusha", false)] 25 | partial class PushaParser; 26 | [OperationParser("Popa", false)] 27 | partial class PopaParser; -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Exceptions/CpuExceptionType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Exceptions; 2 | 3 | /// 4 | /// Exceptions are classified as: 5 | /// Faults: These can be corrected and the program may continue as if nothing happened.
6 | /// Traps: Traps are reported immediately after the execution of the trapping instruction.
7 | /// Aborts: Some severe unrecoverable error. 8 | ///
9 | [Flags] 10 | public enum CpuExceptionType { 11 | /// 12 | /// These can be corrected and the program may continue as if nothing happened. 13 | /// 14 | Fault = 1, 15 | /// 16 | /// Traps are reported immediately after the execution of the trapping instruction. 17 | /// 18 | Trap = 2, 19 | /// 20 | /// Some severe unrecoverable error. 21 | /// 22 | Abort = 4 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Exceptions/CpuInvalidOpcodeException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Exceptions; 2 | 3 | /// 4 | /// The Invalid Opcode exception occurs when the processor tries to execute an invalid or undefined opcode, or an 5 | /// instruction with invalid prefixes. It also occurs in other cases, such as:
6 | /// - The instruction length exceeds 15 bytes, but this only occurs with redundant prefixes.
7 | /// - The instruction tries to access a non-existent control register (for example, mov cr6, eax).
8 | /// - The UD instruction is executed.
9 | /// The saved instruction pointer points to the instruction which caused the exception. 10 | ///
11 | public class CpuInvalidOpcodeException : CpuException { 12 | /// 13 | public CpuInvalidOpcodeException(string message) 14 | : base(message, 0x06, CpuExceptionType.Fault, "#UD") { 15 | } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/IInstructionExecutor.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU; 2 | 3 | using Spice86.Core.Emulator.VM; 4 | 5 | /// 6 | /// API contract for an executor used by the , typically a CPU 7 | /// 8 | public interface IInstructionExecutor { 9 | /// 10 | /// Executes the next instruction. 11 | /// 12 | public void ExecuteNext(); 13 | 14 | /// 15 | /// Signal that we are at the entry point of the program ready to start executing our very first instruction 16 | /// 17 | public void SignalEntry(); 18 | 19 | /// 20 | /// Signal that emulation just stopped, no more instruction will be executed 21 | /// 22 | public void SignalEnd(); 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/InstructionsImpl/Grp2CountSource.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.InstructionsImpl; 2 | 3 | using Spice86.Core.Emulator.CPU; 4 | 5 | /// 6 | /// Enum representing the source of the count for Group 2 instructions in the CPU. 7 | /// 8 | public enum Grp2CountSource 9 | { 10 | /// 11 | /// Represents a count source of one. 12 | /// 13 | One, 14 | 15 | /// 16 | /// Represents a count source of the CL register. 17 | /// 18 | CL, 19 | 20 | /// 21 | /// Represents a count source of the next unsigned 8-bit integer from memory pointed by . 22 | /// 23 | NextUint8 24 | } 25 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/InterruptVectorTable.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU; 2 | 3 | using Spice86.Core.Emulator.Memory.ReaderWriter; 4 | using Spice86.Core.Emulator.ReverseEngineer.DataStructure.Array; 5 | 6 | /// 7 | /// Wraps reads and writes to the Interrupt Vector Table (IVT) 8 | /// 9 | public class InterruptVectorTable : SegmentedAddressArray { 10 | /// 11 | /// Initializes a new instance. 12 | /// 13 | /// The memory bus. 14 | public InterruptVectorTable(IByteReaderWriter memory) : base(memory, 0, 0x100) { 15 | } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/InvalidGroupIndexException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU; 2 | 3 | using Spice86.Core.Emulator.Errors; 4 | using Spice86.Shared.Utils; 5 | 6 | /// 7 | /// The exception thrown when an Invalid Group Index was encountered. 8 | /// 9 | public class InvalidGroupIndexException : InvalidVMOperationException { 10 | /// 11 | /// Initializes a new instance. 12 | /// 13 | /// The class that contains the CPU Registers and Flags 14 | /// The invalid group index to put in the message, converted to hexadecimal 15 | public InvalidGroupIndexException(State state, int groupIndex) : base(state, $"Invalid group index {ConvertUtils.ToHex((uint)groupIndex)}") { 16 | } 17 | public InvalidGroupIndexException(State state, uint groupIndex) : this(state, (int)groupIndex) { 18 | } 19 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/MemoryAddressMandatoryException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU; 2 | 3 | using Spice86.Core.Emulator.Errors; 4 | 5 | public class MemoryAddressMandatoryException : InvalidVMOperationException { 6 | public MemoryAddressMandatoryException(State state) : base(state, 7 | "Memory address is mandatory for this instruction") { 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/GeneralRegisters.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | /// 4 | /// Represents the x86 registers. 5 | /// 6 | public class GeneralRegisters : RegistersHolder { 7 | public GeneralRegisters() : base(8) { 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/RegistersIndexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | using Spice86.Core.Emulator.Memory.Indexer; 4 | 5 | using System.Numerics; 6 | 7 | /// 8 | /// Accessor for registers accessible via index. 9 | /// 10 | /// 11 | public abstract class RegistersIndexer : Indexer 12 | where T : IUnsignedNumber { 13 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/SegmentRegisterIndex.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | public enum SegmentRegisterIndex { 4 | /// 5 | /// The index of the ES (extra segment) register. 6 | /// 7 | EsIndex = 0, 8 | 9 | /// 10 | /// The index of the CS (code segment) register. 11 | /// 12 | CsIndex = 1, 13 | 14 | /// 15 | /// The index of the SS (stack segment) register. 16 | /// 17 | SsIndex = 2, 18 | 19 | /// 20 | /// The index of the DS (data segment) register. 21 | /// 22 | DsIndex = 3, 23 | 24 | /// 25 | /// The index of the FS register. 26 | /// 27 | FsIndex = 4, 28 | 29 | /// 30 | /// The index of the GS register. 31 | /// 32 | GsIndex = 5 33 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/SegmentRegisters.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | /// 4 | /// A class that represents the segment registers of a CPU.
5 | /// The segment registers are registers that store segment selectors, which are used to access different parts of memory. 6 | ///
7 | public class SegmentRegisters : RegistersHolder { 8 | public SegmentRegisters() : base(6) { 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/UInt16RegistersIndexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | using Spice86.Core.Emulator.Memory.ReaderWriter; 4 | 5 | /// 6 | /// Accesses 16-bit registers based on a given index. 7 | /// 8 | public class UInt16RegistersIndexer : RegistersIndexer { 9 | private readonly IUIntReaderWriter _uIntArrayReaderWriter; 10 | 11 | public UInt16RegistersIndexer(IUIntReaderWriter uIntArrayReaderWriter) { 12 | _uIntArrayReaderWriter = uIntArrayReaderWriter; 13 | } 14 | 15 | public override ushort this[uint index] { 16 | get => (ushort)_uIntArrayReaderWriter[index]; 17 | set { 18 | uint currentValue = _uIntArrayReaderWriter[index]; 19 | uint newValue = (currentValue & 0xFFFF0000) | value; 20 | _uIntArrayReaderWriter[index] = newValue; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/CPU/Registers/UInt32RegistersIndexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.CPU.Registers; 2 | 3 | using Spice86.Core.Emulator.Memory.ReaderWriter; 4 | 5 | /// 6 | /// Accesses 32-bit registers based on a given index. 7 | /// 8 | public class UInt32RegistersIndexer : RegistersIndexer { 9 | private readonly IUIntReaderWriter _uIntArrayReaderWriter; 10 | 11 | public UInt32RegistersIndexer(IUIntReaderWriter uIntArrayReaderWriter) { 12 | _uIntArrayReaderWriter = uIntArrayReaderWriter; 13 | } 14 | 15 | public override uint this[uint index] { 16 | get => _uIntArrayReaderWriter[index]; 17 | set => _uIntArrayReaderWriter[index] = value; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/ExternalInput/SelectedReadRegister.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.ExternalInput; 2 | 3 | /// 4 | /// Specifies which register to read from when using the CommandRead or DataRead method. 5 | /// 6 | enum SelectedReadRegister { 7 | InServiceRegister, InterruptRequestRegister 8 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Input/Keyboard/KeyboardCommand.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Input.Keyboard; 2 | 3 | /// 4 | /// Keyboard commands that can be sent to the keyboard controller.
5 | /// https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html#kcc60
6 | /// A20 Gate commands:
7 | /// https://mrhopehub.github.io/2014/12/26/enabling-the-A20-Gate.html 8 | ///
9 | public enum KeyboardCommand : byte { 10 | /// 11 | /// No command set. 12 | /// 13 | None = 0x0, 14 | 15 | /// 16 | /// Enable A20 Address Line 17 | /// 18 | EnableA20Gate = 0xDD, 19 | 20 | /// 21 | /// Disable A20 Address Line 22 | /// 23 | DisableA20Gate = 0xDF, 24 | 25 | /// 26 | /// Write to the output port 27 | /// 28 | SetOutputPort = 0xD1, 29 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Input/Keyboard/KeyboardPorts.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Input.Keyboard; 2 | 3 | /// 4 | /// IDs of keyboard ports for both read and write.
5 | /// https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html 6 | ///
7 | public static class KeyboardPorts { 8 | /// 9 | /// Port used by the CPU to read the input buffer, or write to the output buffer, of the keyboard controller. 10 | /// 11 | public const byte Data = 0x60; 12 | 13 | /// 14 | /// Port that can be used by the CPU to read the status register of the keyboard controller. 15 | /// 16 | public const byte StatusRegister = 0x64; 17 | 18 | /// 19 | /// If the CPU writes to port 0x64, the byte is interpreted as a command byte. 20 | /// 21 | public const byte Command = 0x64; 22 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Input/Mouse/MouseType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Input.Mouse; 2 | 3 | /// 4 | /// The type of mouse. 5 | /// 6 | public enum MouseType { 7 | /// 8 | /// No mouse. 9 | /// 10 | None, 11 | 12 | /// 13 | /// PS/2 mouse (with 3 buttons) 14 | /// 15 | Ps2, 16 | 17 | /// 18 | /// PS/2 mouse with wheel (and 3 buttons) TODO: not implemented 19 | /// 20 | Ps2Wheel, 21 | 22 | /// 23 | /// Microsoft InPort mouse TODO: not implemented 24 | /// 25 | InPort, 26 | 27 | /// 28 | /// Serial port mouse TODO: not implemented 29 | /// 30 | Serial, 31 | 32 | /// 33 | /// Bus mouse TODO: not implemented 34 | /// 35 | Bus 36 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/AudioEngine.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound; 2 | 3 | /// 4 | /// Available audio engines. 5 | /// 6 | public enum AudioEngine { PortAudio, Dummy } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/BlasterState.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// Specifies the current state of the DSP command processor. 5 | /// 6 | public enum BlasterState { 7 | /// 8 | /// The DSP is ready to receive a command. 9 | /// 10 | WaitingForCommand, 11 | /// 12 | /// The DSP is waiting for all of a command's parameters to be written. 13 | /// 14 | ReadingCommand, 15 | /// 16 | /// A one has been written to the reset port. 17 | /// 18 | ResetRequest, 19 | /// 20 | /// The reset port has changed from 1 to 0 and the DSP is resetting. 21 | /// 22 | Resetting 23 | } 24 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/CompressionLevel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// Represents a Sound Blaster PCM compression level. 5 | /// 6 | public enum CompressionLevel { 7 | /// 8 | /// The data is not compressed. 9 | /// 10 | None, 11 | /// 12 | /// The data is compressed using ADPCM2. 13 | /// 14 | ADPCM2, 15 | /// 16 | /// The data is compressed using ADPCM3. 17 | /// 18 | ADPCM3, 19 | /// 20 | /// The data is compressed using ADPCM4. 21 | /// 22 | ADPCM4 23 | } 24 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/DspState.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// All the possible states the SoundBlaster DSP can be in. 5 | /// 6 | public enum DspState : byte { 7 | /// 8 | /// The DSP was reset. 9 | /// 10 | Reset, 11 | /// 12 | /// The DSP is awaiting a Reset 13 | /// 14 | ResetWait, 15 | /// 16 | /// The DSP is available 17 | /// 18 | Normal 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/IBlasterEnvVarProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// Represents a component that defines a BLASTER variable environnement to DOS, for Sound Blaster compatibility and auto-detection 5 | /// 6 | public interface IBlasterEnvVarProvider { 7 | /// 8 | /// The BLASTER string which specifies parameters such as the address, low IRQ, high IRQ, and DMA.
9 | /// For example: 'A220 I5 D1 H5 P330 T6' 10 | ///
11 | string BlasterString { get; } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/InterruptStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | using System; 4 | 5 | /// 6 | /// Represents the contents of the Interrupt Status register. 7 | /// 8 | [Flags] 9 | public enum InterruptStatus { 10 | /// 11 | /// The register is clear. 12 | /// 13 | None = 0, 14 | /// 15 | /// An 8-bit DMA IRQ occurred. 16 | /// 17 | Dma8 = 1, 18 | /// 19 | /// A 16-bit DMA IRQ occurred. 20 | /// 21 | Dma16 = 2, 22 | /// 23 | /// An MPU-401 IRQ occurred. 24 | /// 25 | Mpu401 = 4 26 | } 27 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/MixerRegisters.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// This class contains the register addresses for the SoundBlaster mixer. 5 | /// 6 | public static class MixerRegisters { 7 | /// 8 | /// The register address for the IRQ (interrupt request) bit. 9 | /// 10 | public const byte IRQ = 0x80; 11 | 12 | /// 13 | /// The register address for the DMA (direct memory access) bit. 14 | /// 15 | public const byte DMA = 0x81; 16 | 17 | /// 18 | /// The register address for the interrupt status. 19 | /// 20 | public const byte InterruptStatus = 0x82; 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/SbType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// List of SoundBlaster types. Decides minor differences in the hardware. 5 | /// 6 | public enum SbType { 7 | /// 8 | /// SoundBlaster 16 9 | /// 10 | Sb16 = 6, 11 | /// 12 | /// SoundBlaster Pro 13 | /// 14 | SbPro1 = 2, 15 | 16 | /// 17 | /// SoundBlaster Pro 2 18 | /// 19 | SbPro2 = 4, 20 | } 21 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Blaster/SoundBlasterHardwareConfig.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Blaster; 2 | 3 | /// 4 | /// Depending on the SoundBlaster variant, these can change. 5 | /// 6 | /// Defaults is 5. 7 | /// Defaults is 1. 8 | /// Default is 5. 9 | /// The type of SoundBlaster card to emulate. Defaults to SoundBlaster 16. 10 | public record SoundBlasterHardwareConfig(byte Irq, byte LowDma, byte HighDma, SbType SbType); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/IRequestInterrupt.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound; 2 | 3 | /// 4 | /// Represents a hardware component that can raise interrupts 5 | /// 6 | public interface IRequestInterrupt { 7 | /// 8 | /// Raises a hardware interrupt. 9 | /// 10 | void RaiseInterruptRequest(); 11 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Midi/GeneralMidiState.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Midi; 2 | 3 | /// 4 | /// Specifies the current state of the General MIDI device. 5 | /// 6 | public enum GeneralMidiState { 7 | /// 8 | /// The device is in normal mode. 9 | /// 10 | NormalMode, 11 | /// 12 | /// The device is in UART mode. 13 | /// 14 | UartMode 15 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Midi/GeneralMidiStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Midi; 2 | 3 | /// 4 | /// The status of the General MIDI device. 5 | /// 6 | [Flags] 7 | public enum GeneralMidiStatus : byte { 8 | /// 9 | /// The status of the device is unknown. 10 | /// 11 | None = 0, 12 | /// 13 | /// The command port may be written to. 14 | /// 15 | OutputReady = 1 << 6, 16 | /// 17 | /// The data port may be read from. 18 | /// 19 | InputReady = 1 << 7 20 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/PCSpeaker/SpeakerControl.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.PCSpeaker; 2 | 3 | using System; 4 | 5 | /// 6 | /// Possible values of the PC speaker control register. 7 | /// 8 | [Flags] 9 | internal enum SpeakerControl { 10 | /// 11 | /// The register is clear. 12 | /// 13 | Clear = 0, 14 | /// 15 | /// The PC speaker should use the system timer for input. 16 | /// 17 | UseTimer = 1, 18 | /// 19 | /// The PC speaker is on. 20 | /// 21 | SpeakerOn = 2 22 | } 23 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipEngine.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal enum ChipEngine { 3 | Fixed, 4 | Float, 5 | Ideal, 6 | Short, 7 | Count 8 | } 9 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipFixed.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipFixed { 3 | public ChipFixed() { 4 | Regs = new byte[(int)Reg.Count]; 5 | Gains = new short[(int)Reg.T0]; 6 | Taps = new ushort[(int)DatasheetSpecs.TapCount]; 7 | Buffer = new short[(int)DatasheetSpecs.BufferLength]; 8 | Oversampler = new OversamplerFixed[(int)OutputChannel.Count]; 9 | } 10 | 11 | public byte[] Regs { get; set; } 12 | public short[] Gains { get; set; } 13 | public ushort[] Taps { get; set; } 14 | 15 | public short T0d { get; set; } 16 | 17 | public short Tail { get; set; } 18 | 19 | public short[] Buffer { get; set; } 20 | 21 | public int Length => Buffer.Length; 22 | 23 | public OversamplerFixed[] Oversampler { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipFixedProcessData.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipFixedProcessData { 3 | public ChipFixedProcessData() { 4 | Inputs = new short[(int)InputChannel.Count]; 5 | Outputs = new short[(int)OutputChannel.Count][]; 6 | Outputs[0] = new short[(int)DatasheetSpecs.Oversampling]; 7 | Outputs[1] = new short[(int)DatasheetSpecs.Oversampling]; 8 | } 9 | 10 | public short[] Inputs { get; set; } 11 | public short[][] Outputs { get; set; } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipFloat.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipFloat { 3 | public ChipFloat() { 4 | Regs = new byte[(int)Reg.Count]; 5 | Gains = new double[(int)DatasheetSpecs.TapCount]; 6 | Taps = new ushort[(int)DatasheetSpecs.TapCount]; 7 | Buffer = new double[(int)DatasheetSpecs.BufferLength]; 8 | Oversampler = new OversamplerFloat[(int)OutputChannel.Count]; 9 | } 10 | 11 | public byte[] Regs { get; set; } 12 | 13 | public double[] Gains { get; set; } 14 | 15 | public ushort[] Taps { get; set; } 16 | 17 | public double T0d { get; set; } 18 | 19 | public double[] Buffer { get; set; } 20 | 21 | public int Length => Buffer.Length; 22 | 23 | public OversamplerFloat[] Oversampler { get; set; } 24 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipFloatProcessData.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipFloatProcessData { 3 | public ChipFloatProcessData() { 4 | Inputs = new double[(int)InputChannel.Count]; 5 | Outputs = new double[(int)OutputChannel.Count][]; 6 | Outputs[0] = new double[(int)DatasheetSpecs.Oversampling]; 7 | Outputs[1] = new double[(int)DatasheetSpecs.Oversampling]; 8 | } 9 | 10 | public double[] Inputs { get; set; } 11 | public double[][] Outputs { get; set; } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipIdeal.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | 3 | internal struct ChipIdeal 4 | { 5 | public ChipIdeal() { 6 | Regs = new byte[(int)Reg.Count]; 7 | Gains = new double[(int)Reg.T0]; 8 | Taps = new ushort[(int)DatasheetSpecs.TapCount]; 9 | Buffer = Array.Empty(); 10 | } 11 | 12 | public byte[] Regs { get; set; } 13 | 14 | public double[] Gains { get; set; } 15 | 16 | public ushort[] Taps { get; set; } 17 | 18 | public double T0d { get; set; } 19 | 20 | public ushort Tail { get; set; } 21 | 22 | public double[] Buffer { get; set; } 23 | 24 | public int Length => Buffer.Length; 25 | 26 | public ushort SampleRate { get; set; } 27 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipIdealProcessData.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | 3 | internal struct ChipIdealProcessData { 4 | 5 | public ChipIdealProcessData() { 6 | Inputs = new float[(int)InputChannel.Count]; 7 | Outputs = new float[(int)OutputChannel.Count]; 8 | } 9 | 10 | public float[] Inputs { get; set; } 11 | public float[] Outputs { get; set; } 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipShort.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipShort { 3 | public ChipShort() { 4 | Regs = new byte[(int)Reg.Count]; 5 | Gains = new short[(int)DatasheetSpecs.TapCount]; 6 | Taps = new ushort[(int)DatasheetSpecs.TapCount]; 7 | Buffer = new short[(int)DatasheetSpecs.BufferLength]; 8 | } 9 | 10 | public byte[] Regs { get; set; } 11 | 12 | public short[] Gains { get; set; } 13 | 14 | public ushort[] Taps { get; set; } 15 | 16 | public short T0d { get; set; } 17 | 18 | public ushort Tail { get; set; } 19 | 20 | public short[] Buffer { get; set; } 21 | 22 | public int Length => Buffer.Length; 23 | 24 | public ushort SampleRate { get; set; } 25 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/ChipShortProcessData.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct ChipShortProcessData { 3 | public ChipShortProcessData() { 4 | Inputs = new short[(int)InputChannel.Count]; 5 | Outputs = new short[(int)OutputChannel.Count]; 6 | } 7 | 8 | public short[] Inputs { get; set; } 9 | public short[] Outputs { get; set; } 10 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/InputChannel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal enum InputChannel { 3 | Mono, 4 | Count 5 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/OutputChannel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal enum OutputChannel { 3 | Left, 4 | Right, 5 | Count 6 | } 7 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/OversamplerFixed.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct OversamplerFixed { 3 | public OversamplerFixed() { 4 | Buffer = new short[(int)OversamplerSpecs.Length]; 5 | } 6 | public short[] Buffer {get; set;} 7 | } 8 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/OversamplerFloat.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal struct OversamplerFloat { 3 | public OversamplerFloat() { 4 | Buffer = new double[(int)OversamplerSpecs.Length]; 5 | } 6 | public double[] Buffer { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/OversamplerFloatProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal ref struct OversamplerFloatProcess { 3 | public OversamplerFloatProcess() { 4 | Self = new(); 5 | } 6 | public OversamplerFloat Self { get; set; } 7 | 8 | public double Input { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/OversamplerSpecs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal enum OversamplerSpecs { 3 | Factor = DatasheetSpecs.Oversampling, 4 | Length = 19, 5 | }; 6 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ym7128b/Reg.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ym7128b; 2 | internal enum Reg { 3 | Gl1, 4 | Gl2, 5 | Gl3, 6 | Gl4, 7 | Gl5, 8 | Gl6, 9 | Gl7, 10 | Gl8, 11 | 12 | Gr1, 13 | Gr2, 14 | Gr3, 15 | Gr4, 16 | Gr5, 17 | Gr6, 18 | Gr7, 19 | Gr8, 20 | 21 | Vm, 22 | Vc, 23 | Vl, 24 | Vr, 25 | 26 | C0, 27 | C1, 28 | 29 | T0, 30 | T1, 31 | T2, 32 | T3, 33 | T4, 34 | T5, 35 | T6, 36 | T7, 37 | T8, 38 | 39 | Count 40 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Sound/Ymf262Emu/Channels/BassDrum.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Sound.Ymf262Emu.Channels; 2 | 3 | using Spice86.Core.Emulator.Devices.Sound.Ymf262Emu.Operators; 4 | 5 | internal sealed class BassDrum : Channel2 { 6 | public BassDrum(FmSynthesizer opl) 7 | : base(6, new Operator(0x10, opl), new Operator(0x13, opl), opl) { 8 | } 9 | 10 | public override void GetChannelOutput(Span output) { 11 | // Bass Drum ignores first operator, when it is in series. 12 | if (Cnt == 1) { 13 | if (Op1 != null) { 14 | Op1.Ar = 0; 15 | } 16 | } 17 | 18 | base.GetChannelOutput(output); 19 | } 20 | 21 | // Key ON and OFF are unused in rhythm channels. 22 | public override void KeyOn() { 23 | } 24 | 25 | public override void KeyOff() { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Timer/InvalidCounterIndexException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Timer; 2 | 3 | using Spice86.Core.Emulator.CPU; 4 | using Spice86.Core.Emulator.Errors; 5 | 6 | /// 7 | /// The exception thrown when an invalid counter index is used in the Programmable Interval Timer. 8 | /// 9 | public class InvalidCounterIndexException : InvalidVMOperationException { 10 | /// 11 | /// Initializes a new instance. 12 | /// 13 | /// The CPU state. 14 | /// The incorrect counter index that triggered the exception. 15 | public InvalidCounterIndexException(State state, int counterIndex) : base(state, $"Invalid counter index {counterIndex}") { 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/BitManipulationExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video; 2 | 3 | internal static class BitManipulationExtensions { 4 | /// 5 | /// Rotate right by the specified amount. 6 | /// 7 | public static void Ror(ref this byte value, int amount) { 8 | value = (byte)(value << 8 - amount | value >> amount); 9 | } 10 | 11 | /// 12 | /// Split a byte into an array of eight booleans. 13 | /// 14 | public static bool[] ToBits(this byte value) { 15 | bool[] b = new bool[8]; 16 | for (int i = 0; i < 8; i++) { 17 | b[i] = (value & 1 << i) != 0; 18 | } 19 | return b; 20 | } 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/IVideoMemory.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video; 2 | 3 | using Spice86.Core.Emulator.Memory; 4 | 5 | /// 6 | /// Represents the video memory interface for managing video memory. 7 | /// 8 | public interface IVideoMemory : IMemoryDevice { 9 | /// 10 | /// Provides access to the 4 planes of video memory. 11 | /// 12 | byte[,] Planes { get; } 13 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/AttributeController/ColorSelectRegister.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers.AttributeController; 2 | 3 | /// 4 | /// Represents the 8 bit Color Select register. 5 | /// 6 | public class ColorSelectRegister : Register8 { 7 | /// 8 | /// Use these 2 bits as bits 4 and 5 of the color attribute when 9 | /// 10 | /// is set. 11 | /// 12 | public byte Bits45 { 13 | get => GetBits(1, 0); 14 | set => SetBits(1, 0, value); 15 | } 16 | 17 | /// 18 | /// Use these 2 bits as bits 6 and 7 of the color attribute, except in mode 13 19 | /// 20 | public byte Bits67 { 21 | get => GetBits(1, 0); 22 | set => SetBits(1, 0, value); 23 | } 24 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/CrtController/OverflowRegister.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers.CrtController; 2 | 3 | /// 4 | /// Represents the 8 bit Overflow register. 5 | /// 6 | public class OverflowRegister : Register8 { 7 | public int VerticalTotal89 => (GetBit(0) ? 1 << 8 : 0) | (GetBit(5) ? 1 << 9 : 0); 8 | public int VerticalDisplayEnd89 => (GetBit(1) ? 1 << 8 : 0) | (GetBit(6) ? 1 << 9 : 0); 9 | public int VerticalSyncStart89 => (GetBit(2) ? 1 << 8 : 0) | (GetBit(7) ? 1 << 9 : 0); 10 | public int VerticalBlankingStart8 => GetBit(3) ? 1 << 8 : 0; 11 | public int LineCompare8 => GetBit(4) ? 1 << 8 : 0; 12 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/Enums/SequencerRegister.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers.Enums; 2 | 3 | /// 4 | /// Names of the sequencer registers. 5 | /// 6 | public enum SequencerRegister { 7 | /// 8 | /// Reset Register 9 | /// 10 | Reset, 11 | 12 | /// 13 | /// Clocking Mode Register 14 | /// 15 | ClockingMode, 16 | 17 | /// 18 | /// Map Mask Register 19 | /// 20 | PlaneMask, 21 | 22 | /// 23 | /// Character Map Select Register 24 | /// 25 | CharacterMapSelect, 26 | 27 | /// 28 | /// Sequencer Memory Mode Register 29 | /// 30 | MemoryMode 31 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/General/InputStatusRegister0.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers.General; 2 | 3 | /// 4 | /// The address for this read-only register is address hex 03C2. 5 | /// Do not write to this register. 6 | /// 7 | public class InputStatusRegister0 : Register8 { 8 | /// 9 | /// When the CRT Interrupt field (bit 7) is 1, a vertical retrace interrupt is pending. 10 | /// 11 | public bool CrtInterrupt { 12 | get => GetBit(7); 13 | set => SetBit(7, value); 14 | } 15 | 16 | /// 17 | /// BIOS uses the Switch Sense field (bit 4) in determining the type of display attached. 18 | /// 19 | public bool SwitchSense { 20 | get => GetBit(4); 21 | set => SetBit(4, value); 22 | } 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/GeneralRegisters.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers; 2 | 3 | using Spice86.Core.Emulator.Devices.Video.Registers.General; 4 | 5 | /// 6 | /// Represents the general registers of the VGA. 7 | /// 8 | public class GeneralRegisters { 9 | /// 10 | /// Get the Miscellaneous Output register. 11 | /// 12 | public MiscellaneousOutput MiscellaneousOutput { get; init; } = new(); 13 | 14 | /// 15 | /// Get the Input Status Register 0. 16 | /// 17 | public InputStatusRegister0 InputStatusRegister0 { get; init; } = new(); 18 | 19 | /// 20 | /// Get the Input Status Register 1. 21 | /// 22 | public InputStatusRegister1 InputStatusRegister1 { get; init; } = new(); 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Devices/Video/Registers/Graphics/ReadMapSelectRegister.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Devices.Video.Registers.Graphics; 2 | 3 | /// 4 | /// Represents the 8 bit Read Map Select register. 5 | /// 6 | public class ReadMapSelectRegister : Register8 { 7 | /// 8 | /// This field specifies the display memory plane for Read mode 0. 9 | /// 10 | public byte PlaneSelect { 11 | get => GetBits(1, 0); 12 | set => SetBits(1, 0, value); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Errors/UnhandledOperationException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Errors; 2 | 3 | using Spice86.Core.Emulator.CPU; 4 | 5 | /// 6 | /// Exception thrown when an unsupported or invalid operation is requested. 7 | /// 8 | public class UnhandledOperationException : InvalidVMOperationException { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The CPU state when the exception occured. 13 | /// The error message that explains the reason for the exception. 14 | public UnhandledOperationException(State state, string message) : base(state, message) { 15 | } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Function/ByteModificationRecord.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Function; 2 | 3 | /// 4 | /// An immutable representation of a byte change. 5 | /// 6 | /// The old byte value. 7 | /// The new byte value. 8 | public readonly record struct ByteModificationRecord(byte OldValue, byte NewValue); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Function/CallType.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Function; 2 | 3 | using Spice86.Core.Emulator.CPU; 4 | 5 | /// 6 | /// All the call conventions supported by the 7 | /// 8 | public enum CallType { 9 | /// For this call, only IP is on the stack. 10 | NEAR, 11 | 12 | /// For this call, CS and IP are on the stack 13 | FAR, 14 | 15 | /// For this call, CS, IP, and the flags are on the stack. 16 | INTERRUPT, 17 | 18 | /// Same as INTERRUPT but not triggered by an instruction. 19 | EXTERNAL_INTERRUPT, 20 | 21 | /// Means called by the VM itself and not by emulated code. 22 | MACHINE, 23 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Function/FunctionReturn.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Function; 2 | 3 | using System; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | /// 7 | /// Represents a function return in the emulator, including information about the return call type and the return address. 8 | /// 9 | /// The calling convention. 10 | /// The return address. 11 | public readonly record struct FunctionReturn(CallType ReturnCallType, SegmentedAddress Address) : IComparable { 12 | /// 13 | public int CompareTo(FunctionReturn other) { 14 | return Address.CompareTo(other.Address); 15 | } 16 | 17 | /// 18 | public override string ToString() { 19 | return $"{ReturnCallType} at {Address}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Function/IFunctionHandlerProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Function; 2 | 3 | public interface IFunctionHandlerProvider { 4 | public FunctionHandler FunctionHandlerInUse { get; } 5 | public bool IsInitialExecutionContext { get; } 6 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/IOPorts/UnhandledIOPortException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.IOPorts; 2 | 3 | using Spice86.Core.Emulator.CPU; 4 | using Spice86.Core.Emulator.Errors; 5 | using Spice86.Shared.Utils; 6 | 7 | /// 8 | /// Thrown when an unhandled IO Port is accessed. 9 | /// 10 | public class UnhandledIOPortException : UnhandledOperationException { 11 | /// 12 | /// Initializes a new instance of the class with the specified machine and IO Port number. 13 | /// 14 | /// The CPU state when the exception occured. 15 | /// The number of the unhandled IO Port. 16 | public UnhandledIOPortException(State state, int ioPort) : base(state, $"Unhandled port {ConvertUtils.ToHex((uint)ioPort)}. This usually means that the hardware behind the port is not emulated or that the port is not routed correctly.") { 17 | } 18 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Common/IndexBasedDispatcher/IRunnable.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Common.IndexBasedDispatcher; 2 | 3 | /// 4 | /// The base interface for classes that can be called back. 5 | /// 6 | public interface IRunnable { 7 | /// 8 | /// The code to invoke when calling back. 9 | /// 10 | public void Run(); 11 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Common/IndexBasedDispatcher/RunnableAction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Common.IndexBasedDispatcher; 2 | 3 | /// 4 | /// An action wrapped inside a IRunnable object. Calling Run invokes the action. 5 | /// 6 | public class RunnableAction : IRunnable { 7 | private readonly Action _action; 8 | 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// A class that encapsulates a method with no parameters which returns nothing. 13 | public RunnableAction(Action action) { 14 | _action = action; 15 | } 16 | 17 | /// 18 | public void Run() { 19 | _action.Invoke(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Common/RoutineInstall/IAssemblyRoutineWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Common.RoutineInstall; 2 | 3 | using Spice86.Core.Emulator.InterruptHandlers.Common.MemoryWriter; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | /// 7 | /// Interface for objects that need assembly routine to be in ram 8 | /// 9 | public interface IAssemblyRoutineWriter { 10 | /// 11 | /// Writes the ASM implementation of the Interrupt handler in emulated RAM. 12 | /// 13 | /// The class that writes ASM to the Memory Bus. 14 | public SegmentedAddress WriteAssemblyInRam(MemoryAsmWriter memoryAsmWriter); 15 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Dos/Ems/EmmMemory.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Dos.Ems; 2 | 3 | /// 4 | /// Expanded memory is divided into segments called logical pages.
5 | /// These pages are typically 16K-bytes of memory.
6 | /// Logical pages are accessed through a physical block of memory called a page frame.
7 | /// The page frame contains multiple physical pages, pages that the
8 | /// CPU can address directly. Physical pages are also 16K bytes of memory.
9 | /// This static class only defines a few constants. 10 | ///
11 | public static class EmmMemory { 12 | /// 13 | /// 8 MB of Expanded Memory (LIM 3.2 specs) 14 | /// 15 | public const uint EmmMemorySize = 8 * 1024 * 1024; 16 | 17 | /// 18 | /// The total number of logical pages possible in 8 MB of expanded memory. 19 | /// 20 | public const ushort TotalPages = 512; 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/IInterruptHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers; 2 | 3 | using Spice86.Core.Emulator.InterruptHandlers.Common.RoutineInstall; 4 | 5 | /// 6 | /// Interface for C# interrupt handlers.
7 | /// Interrupt handlers write their ASM code in emulated memory. 8 | ///
9 | public interface IInterruptHandler : IAssemblyRoutineWriter { 10 | /// 11 | /// Vector number of the interrupt being represented 12 | /// 13 | public byte VectorNumber { get; } 14 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Input/Mouse/MouseStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Input.Mouse; 2 | 3 | /// 4 | /// Mouse status 5 | /// 6 | /// The X axis position 7 | /// They Y axis position 8 | /// The state of the button flags 9 | public record struct MouseStatus(int X, int Y, int ButtonFlags) { 10 | /// 11 | public override string ToString() { 12 | return string.Format("x = {0}, y = {1}, leftButton = {2}, rightButton = {3}, middleButton = {4}" 13 | , X, Y, (ButtonFlags & 1) == 1 ? "down" : "up", (ButtonFlags & 2) == 2 ? "down" : "up", (ButtonFlags & 4) == 4 ? "down" : "up"); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/Input/Mouse/MouseUserCallback.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.Input.Mouse; 2 | 3 | using Spice86.Core.Emulator.Devices.Input.Mouse; 4 | 5 | /// 6 | /// Represents a user-defined callback function for when a mouse event occurs. 7 | /// 8 | /// Specify the mask of which event types to trigger on 9 | /// Segment of address to call when matching event happens 10 | /// Offset of address to call when matching event happens 11 | public record struct MouseUserCallback(MouseEventMask TriggerMask, ushort Segment, ushort Offset); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Enums/MemoryAction.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Enums; 2 | 3 | /// 4 | /// Represents a memory action. 5 | /// 6 | internal enum MemoryAction { 7 | /// 8 | /// Reads a byte from memory. 9 | /// 10 | ReadByte, 11 | 12 | /// 13 | /// Writes a byte to memory. 14 | /// 15 | WriteByte, 16 | 17 | /// 18 | /// Sets a block of memory to a value. 19 | /// 20 | MemSet, 21 | 22 | /// 23 | /// Moves a block of memory. 24 | /// 25 | MemMove 26 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Enums/MemoryModel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Enums; 2 | 3 | /// 4 | /// Represents the memory model. 5 | /// 6 | public enum MemoryModel { 7 | /// 8 | /// Text memory layout. 9 | /// 10 | Text, 11 | 12 | /// 13 | /// CGA memory layout. 14 | /// 15 | Cga, 16 | 17 | /// 18 | /// Planar memory layout. 19 | /// 20 | Planar, 21 | 22 | /// 23 | /// Packed memory layout. 24 | /// 25 | Packed 26 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Enums/ModeFlags.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Enums; 2 | 3 | /// 4 | /// Vga Mode setup flags. 5 | /// 6 | [Flags] 7 | public enum ModeFlags { 8 | /// 9 | /// Unknown. 10 | /// 11 | Legacy = 0x0001, 12 | 13 | /// 14 | /// Indicates that colors need to be converted to grayscale. 15 | /// 16 | GraySum = 0x0002, 17 | 18 | /// 19 | /// Indicates that the default palette should not be loaded. 20 | /// 21 | NoPalette = 0x0008, 22 | 23 | /// 24 | /// Indicates that the video memory should not be cleared. 25 | /// 26 | NoClearMem = 0x8000 27 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Records/Area.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 2 | 3 | /// 4 | /// Represents a rectangle. 5 | /// 6 | public record struct Area(int Width, int Height); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Records/CharacterPlusAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 2 | 3 | /// 4 | /// Represents a character with an attribute. 5 | /// 6 | /// The ASCII code of a character 7 | /// The byte that describes color, blinking and charset 8 | /// Whether the attribute needs to be used 9 | public readonly record struct CharacterPlusAttribute(char Character, byte Attribute, bool UseAttribute); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Records/CursorPosition.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 2 | 3 | /// 4 | /// Represents a cursor position. 5 | /// 6 | /// X position in columns 7 | /// Y position ion rows 8 | /// Which of the 8 text pages the cursor position is for 9 | public record struct CursorPosition(int X, int Y, int Page); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Records/GraphicsOperation.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 2 | 3 | using Spice86.Core.Emulator.InterruptHandlers.VGA.Enums; 4 | 5 | /// 6 | /// Represents a graphics operation. 7 | /// 8 | internal record struct GraphicsOperation(VgaMode VgaMode, int LineLength, int DisplayStart, MemoryAction MemoryAction, int X, int Y, byte[] Pixels, int Width, int Height, int Lines); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/Records/VgaMode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 2 | 3 | using Spice86.Core.Emulator.InterruptHandlers.VGA.Enums; 4 | 5 | /// 6 | /// Represents a VGA mode. 7 | /// 8 | /// The memory model to use when drawing 9 | /// The width to tell the BIOS 10 | /// The height to tell the BIOS 11 | /// The color depth to use in drawing 12 | /// The default width of characters in this mode 13 | /// The default height of characters in this mode 14 | /// Which segment this mode uses 15 | public readonly record struct VgaMode(MemoryModel MemoryModel, ushort Width, ushort Height, byte BitsPerPixel, byte CharacterWidth, byte CharacterHeight, ushort StartSegment); -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/VgaConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA; 2 | 3 | /// 4 | /// Defines a few VGA constants. 5 | /// 6 | public static class VgaConstants { 7 | /// 8 | /// The segment of the graphics memory. 9 | /// 10 | public const ushort GraphicsSegment = 0xA000; 11 | 12 | /// 13 | /// The segment of the text memory. 14 | /// 15 | public const ushort ColorTextSegment = 0xB800; 16 | 17 | /// 18 | /// The segment of the monochrome text memory. 19 | /// 20 | public const ushort MonochromeTextSegment = 0xB000; 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/InterruptHandlers/VGA/VideoModeChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.InterruptHandlers.VGA; 2 | 3 | using Spice86.Core.Emulator.InterruptHandlers.VGA.Records; 4 | 5 | /// 6 | /// Event arguments for the video mode changed event. 7 | /// 8 | public readonly record struct VideoModeChangedEventArgs { 9 | /// 10 | /// Instantiates a new instance of . 11 | /// 12 | /// The new video mode. 13 | public VideoModeChangedEventArgs(VgaMode newMode) { 14 | NewMode = newMode; 15 | } 16 | 17 | /// 18 | /// The new video mode. 19 | /// 20 | public VgaMode NewMode { get; init; } 21 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/DmaTransferMode.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory; 2 | 3 | /// 4 | /// Specifies the transfer mode of a DMA channel. 5 | /// 6 | public enum DmaTransferMode { 7 | /// 8 | /// The DMA channel is in single-cycle mode. 9 | /// 10 | SingleCycle, 11 | 12 | /// 13 | /// The DMA channel is in auto-initialize mode. 14 | /// 15 | AutoInitialize 16 | } 17 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/IDmaDevice16.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory; 2 | 3 | using System; 4 | 5 | /// 6 | /// Defines a device which supports 16-bit DMA transfers. 7 | /// 8 | public interface IDmaDevice16 { 9 | /// 10 | /// Gets the DMA channel of the device. 11 | /// 12 | int Channel { get; } 13 | 14 | /// 15 | /// Writes 16-bit words of data to the DMA device. 16 | /// 17 | /// Address of first 16-bit word to write to the device. 18 | /// Number of 16-bit words to write. 19 | /// Number of 16-bit words actually written to the device. 20 | int WriteWords(IntPtr source, int count); 21 | 22 | /// 23 | /// Invoked when a transfer is completed in single-cycle mode. 24 | /// 25 | void SingleCycleComplete(); 26 | } 27 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/IDmaDevice8.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory; 2 | 3 | using System; 4 | 5 | /// 6 | /// Defines a device which supports 8-bit DMA transfers. 7 | /// 8 | public interface IDmaDevice8 { 9 | /// 10 | /// Gets the DMA channel of the device. 11 | /// 12 | int Channel { get; } 13 | 14 | /// 15 | /// Writes bytes of data to the DMA device. 16 | /// 17 | /// Bytes to write to the device. 18 | /// Number of bytes actually written to the device. 19 | int WriteBytes(ReadOnlySpan source); 20 | 21 | /// 22 | /// Invoked when a transfer is completed in single-cycle mode. 23 | /// 24 | void SingleCycleComplete(); 25 | } 26 | -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/Indexer/Int16Indexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.Indexer; 2 | 3 | /// 4 | /// Provides indexed signed short access over memory. 5 | /// 6 | public class Int16Indexer : MemoryIndexer { 7 | private readonly UInt16Indexer _uInt16Indexer; 8 | 9 | /// 10 | /// Initializes a new instance of the class with the specified uInt16Indexer. 11 | /// 12 | /// Where data is read and written. 13 | public Int16Indexer(UInt16Indexer uInt16Indexer) => _uInt16Indexer = uInt16Indexer; 14 | 15 | /// 16 | public override short this[uint address] { 17 | get => (short)_uInt16Indexer[address]; 18 | set => _uInt16Indexer[address] = (ushort)value; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/Indexer/Int32ndexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.Indexer; 2 | 3 | /// 4 | /// Provides indexed signed int access over memory. 5 | /// 6 | public class Int32Indexer : MemoryIndexer { 7 | private readonly UInt32Indexer _uInt32Indexer; 8 | 9 | /// 10 | /// Initializes a new instance of the class with the specified uInt32Indexer. 11 | /// 12 | /// Where data is read and written. 13 | public Int32Indexer(UInt32Indexer uInt32Indexer) => _uInt32Indexer = uInt32Indexer; 14 | 15 | /// 16 | public override int this[uint address] { 17 | get => (int)_uInt32Indexer[address]; 18 | set => _uInt32Indexer[address] = (uint)value; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/Indexer/Int8Indexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.Indexer; 2 | 3 | /// 4 | /// Provides indexed signed byte access over memory. 5 | /// 6 | public class Int8Indexer : MemoryIndexer { 7 | private readonly UInt8Indexer _uInt8Indexer; 8 | 9 | /// 10 | /// Initializes a new instance of the class with the specified uInt8Indexer. 11 | /// 12 | /// Where data is read and written. 13 | public Int8Indexer(UInt8Indexer uInt8Indexer) => _uInt8Indexer = uInt8Indexer; 14 | 15 | /// 16 | public override sbyte this[uint address] { 17 | get => (sbyte)_uInt8Indexer[address]; 18 | set => _uInt8Indexer[address] = (byte)value; 19 | } 20 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/Indexer/UInt8Indexer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.Indexer; 2 | 3 | using Spice86.Core.Emulator.Memory.ReaderWriter; 4 | 5 | /// 6 | /// Provides indexed byte access over memory. 7 | /// 8 | public class UInt8Indexer : MemoryIndexer { 9 | private readonly IByteReaderWriter _byteReaderWriter; 10 | 11 | /// 12 | /// Initializes a new instance of the class with the specified byteReadeWriter. 13 | /// 14 | /// Where data is read and written. 15 | public UInt8Indexer(IByteReaderWriter byteReaderWriter) => _byteReaderWriter = byteReaderWriter; 16 | 17 | /// 18 | public override byte this[uint address] { 19 | get => _byteReaderWriter[address]; 20 | set => _byteReaderWriter[address] = value; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/ArrayReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Implementation of IReaderWriter on top of an array of type T 5 | /// 6 | /// 7 | public abstract class ArrayReaderWriter: IReaderWriter { 8 | public T[] Array { get; } 9 | 10 | public ArrayReaderWriter(T[] array) { 11 | Array = array; 12 | } 13 | 14 | /// 15 | public T this[uint address] { 16 | get => Array[address]; 17 | set => Array[address] = value; 18 | } 19 | 20 | /// 21 | public uint Length { get => (uint)Array.Length; } 22 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/ByteArrayReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Implementation of IReaderWriter over a byte array 5 | /// 6 | public class ByteArrayReaderWriter : ArrayReaderWriter, IByteReaderWriter { 7 | public ByteArrayReaderWriter(byte[] array) : base(array) { 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/IBaseAddressProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Interface for classes that provide a BaseAddress uint field. 5 | /// 6 | public interface IBaseAddressProvider { 7 | /// 8 | /// Base address to add to any address used to access the underlying IByteReaderWriter instance. 9 | /// 10 | public uint BaseAddress { get; } 11 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/IByteReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Interface for objects that allow to read and write bytes at specific addresses 5 | /// 6 | public interface IByteReaderWriter: IReaderWriter { 7 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/IReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Interface for objects that allow to read at specific addresses 5 | /// 6 | public interface IReaderWriter { 7 | /// 8 | /// Provides read / write access at address 9 | /// 10 | /// Address where to perform the operation 11 | public T this[uint address] { get; set; } 12 | 13 | /// 14 | /// Length of the address space 15 | /// 16 | public uint Length { get; } 17 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/IUIntReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Interface for objects that allow to read and write bytes at specific addresses 5 | /// 6 | public interface IUIntReaderWriter: IReaderWriter { 7 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/Memory/ReaderWriter/UintArrayReaderWriter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.Memory.ReaderWriter; 2 | 3 | /// 4 | /// Implementation of IReaderWriter over a uint array 5 | /// 6 | public class UIntArrayReaderWriter : ArrayReaderWriter, IUIntReaderWriter { 7 | public UIntArrayReaderWriter(uint[] array) : base(array) { 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/OperatingSystem/Structures/DosTables.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.OperatingSystem.Structures; 2 | 3 | /// 4 | /// Centralizes global DOS memory structures 5 | /// 6 | public class DosTables { 7 | /// 8 | /// The current country information 9 | /// 10 | public CountryInfo CountryInfo { get; set; } = new(); 11 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/ReverseEngineer/DataStructure/MemoryBasedDataStructure.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.ReverseEngineer.DataStructure; 2 | 3 | using Spice86.Core.Emulator.Memory.ReaderWriter; 4 | 5 | /// 6 | /// Represents a memory base structure with a base address. 7 | /// 8 | public class MemoryBasedDataStructure : AbstractMemoryBasedDataStructure { 9 | /// 10 | /// Initializes a new instance. 11 | /// 12 | /// Where data is read and written. 13 | /// The base address of the data structure. 14 | public MemoryBasedDataStructure(IByteReaderWriter byteReaderWriter, uint baseAddress) : base(byteReaderWriter) { 15 | BaseAddress = baseAddress; 16 | } 17 | 18 | /// 19 | /// The base address of the data structure. 20 | /// 21 | public override uint BaseAddress { get; } 22 | } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/VM/Breakpoint/AddressOperation.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.VM.Breakpoint; 2 | 3 | public enum AddressOperation { READ, WRITE, ACCESS } -------------------------------------------------------------------------------- /src/Spice86.Core/Emulator/VM/HaltRequestedException.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Core.Emulator.VM; 2 | 3 | /// 4 | /// Not an error, but generated by HLT instruction in generated code. Allows the machine to stop running properly 5 | /// 6 | public class HaltRequestedException : Exception { 7 | 8 | } -------------------------------------------------------------------------------- /src/Spice86.Core/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This barely affects performance, and breaks the public APIs contract if the method is public")] 9 | [assembly: SuppressMessage("Style", "IDE0007:Use implicit type", Justification = "We don't like 'var' around these parts, partner...")] -------------------------------------------------------------------------------- /src/Spice86.Core/Resources/2MGM.sf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/src/Spice86.Core/Resources/2MGM.sf2 -------------------------------------------------------------------------------- /src/Spice86.Logging/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This barely affects performance, and breaks the public APIs contract if the method is public")] 9 | [assembly: SuppressMessage("Style", "IDE0007:Use implicit type", Justification = "We don't like 'var' around these parts, partner...")] 10 | -------------------------------------------------------------------------------- /src/Spice86.Logging/LoggerPropertyBag.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Logging; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | using Spice86.Shared.Interfaces; 5 | 6 | /// 7 | public class LoggerPropertyBag : ILoggerPropertyBag { 8 | /// 9 | public SegmentedAddress CsIp { get; set; } = new(0,0); 10 | 11 | /// 12 | public int ContextIndex { get; set; } 13 | } -------------------------------------------------------------------------------- /src/Spice86.Logging/Spice86.Logging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Spice86.Logging 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Spice86.MicroBenchmarkTemplate/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using BenchmarkDotNet; 2 | global using BenchmarkDotNet.Attributes; 3 | global using BenchmarkDotNet.Running; 4 | 5 | global using System.Linq; 6 | global using System.Text; 7 | global using System.Threading.Tasks; 8 | global using System.IO; 9 | global using System.Diagnostics; 10 | 11 | global using Spice86; 12 | global using Spice86.Core; 13 | global using Spice86.Logging; 14 | global using Spice86.Shared; 15 | global using Spice86.Tests; 16 | global using Spice86.Shared.Emulator.Memory; 17 | global using Spice86.Core.Emulator.CPU; 18 | -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Keyboard/KeyboardEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Keyboard; 2 | 3 | /// 4 | /// EventArgs for when a keyboard key is down or up. 5 | /// 6 | /// The Key pressed or released. Enum taken from Avalonia. 7 | /// Whether the key is up or down. 8 | /// The IBM PC scan code, for Keyboard emulation. 9 | /// The ASCII code, converted from the scan code. Added to the BIOS keyboard buffer. 10 | public readonly record struct KeyboardEventArgs(Key Key, bool IsPressed, byte? ScanCode, byte? AsciiCode) { 11 | /// 12 | /// Static property representing an empty KeyboardEventArgs instance. 13 | /// 14 | public static KeyboardEventArgs None { get; } = new(Key.None, false, null, null); 15 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Memory/BitWidth.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Memory; 2 | 3 | public enum BitWidth { 4 | BYTE_8, WORD_16, DWORD_32 5 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Mouse/MouseButton.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Mouse; 2 | 3 | /// 4 | /// Identify each mouse button 5 | /// 6 | public enum MouseButton { 7 | /// 8 | /// No mouse button 9 | /// 10 | None, 11 | 12 | /// 13 | /// The left mouse button 14 | /// 15 | Left, 16 | 17 | /// 18 | /// The right mouse button 19 | /// 20 | Right, 21 | 22 | /// 23 | /// The middle mouse button 24 | /// 25 | Middle, 26 | 27 | /// 28 | /// Extra button 1 29 | /// 30 | XButton1, 31 | 32 | /// 33 | /// Extra button 2 34 | /// 35 | XButton2 36 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Mouse/MouseButtonEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Mouse; 2 | 3 | /// 4 | /// Contains the details of the mouse event. 5 | /// 6 | public readonly record struct MouseButtonEventArgs { 7 | /// 8 | /// Instantiates a new instance of . 9 | /// 10 | /// Which, if any, button triggered the event 11 | /// True if that button is pressed 12 | public MouseButtonEventArgs(MouseButton button, bool buttonDown) { 13 | Button = button; 14 | ButtonDown = buttonDown; 15 | } 16 | 17 | /// 18 | /// Whether the button is pressed. 19 | /// 20 | public bool ButtonDown { get; } 21 | 22 | /// 23 | /// Which button triggered the event. 24 | /// 25 | public MouseButton Button { get; } 26 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Mouse/MouseMoveEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Mouse; 2 | 3 | /// 4 | /// Contains the details of a mouse movement event. 5 | /// 6 | public readonly record struct MouseMoveEventArgs { 7 | /// 8 | /// Instantiates a new instance of . 9 | /// 10 | /// The horizontal mouse position on a scale from 0 to 1 11 | /// The vertical mouse position on a scale from 0 to 1 12 | public MouseMoveEventArgs(double x, double y) { 13 | X = x; 14 | Y = y; 15 | } 16 | 17 | /// 18 | /// The horizontal mouse position on a scale from 0 to 1. 19 | /// 20 | public double X { get; } 21 | 22 | /// 23 | /// The vertical mouse position on a scale from 0 to 1. 24 | /// 25 | public double Y { get; } 26 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Video/Rgb.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Video; 2 | 3 | /// 4 | /// RGB representation of a color. 5 | /// 6 | /// Red channel 7 | /// Green channel 8 | /// Blue channel 9 | public readonly record struct Rgb(byte R, byte G, byte B) { 10 | /// 11 | /// Creates a new Rgb instance from a 32-bit unsigned integer value representing a color in the format 0xRRGGBB. 12 | /// 13 | /// The 32-bit unsigned integer value representing a color in the format 0xRRGGBB. 14 | /// A new Rgb instance representing the color. 15 | public static Rgb FromUint(uint value) => new( 16 | (byte)((value >> 16) & 0xff), 17 | (byte)((value >> 8) & 0xff), 18 | (byte)(value & 0xff) 19 | ); 20 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Emulator/Video/UIRenderEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Emulator.Video; 2 | 3 | /// 4 | /// Event Args that pass the WriteableBitmap buffer pointer to the video card for rendering. 5 | /// 6 | /// The pointer to the start of the video buffer 7 | /// The length of the video buffer, in bytes 8 | public readonly record struct UIRenderEventArgs(IntPtr Address, int Length); 9 | -------------------------------------------------------------------------------- /src/Spice86.Shared/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This barely affects performance, and breaks the public APIs contract if the method is public")] 9 | [assembly: SuppressMessage("Style", "IDE0007:Use implicit type", Justification = "We don't like 'var' around these parts, partner...")] 10 | -------------------------------------------------------------------------------- /src/Spice86.Shared/Interfaces/ILoggerPropertyBag.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Interfaces; 2 | 3 | using Spice86.Shared.Emulator.Memory; 4 | 5 | /// 6 | /// Contains properties used internally by the to enrich logs.
7 | /// Each property is updated during execution by the appropriate emulator class. 8 | ///
9 | public interface ILoggerPropertyBag { 10 | /// 11 | /// From Cpu.State.CS and Cpu.State.IP 12 | /// 13 | SegmentedAddress CsIp { get; set; } 14 | 15 | int ContextIndex { get; set; } 16 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Interfaces/IPerformanceMeasurer.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Interfaces; 2 | 3 | /// 4 | /// Measures a performance metric. 5 | /// 6 | public interface IPerformanceMeasurer { 7 | /// 8 | /// Gets the performance measurement value per millisecond. 9 | /// 10 | long ValuePerMillisecond { get; } 11 | 12 | /// 13 | /// Gets the performance measurement value per second. 14 | /// 15 | long ValuePerSecond { get; } 16 | 17 | /// 18 | /// Gets the performance measurement value per second (average). 19 | /// 20 | long AverageValuePerSecond { get; } 21 | 22 | /// 23 | /// Updates performance measurements with a new value. 24 | /// 25 | /// The new total amount for the metric being measured 26 | void UpdateValue(long newMeasure); 27 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Interfaces/IScreenPresenter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Interfaces; 2 | 3 | /// 4 | /// Interface implemented by the UI class that presents video updates on screen. 5 | /// 6 | public interface IScreenPresenter { 7 | /// 8 | /// Event raised when the user interface has started and is able to display the content of the video renderer. 9 | /// 10 | public event Action? UserInterfaceInitialized; 11 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Interfaces/ITimeMultiplier.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.Interfaces; 2 | 3 | /// 4 | /// Interface from the PIT available to the GUI. 5 | /// 6 | public interface ITimeMultiplier { 7 | /// 8 | /// Makes time go faster, or at a normal speed (value: 1) 9 | /// 10 | /// The value by which time will be multiplied 11 | void SetTimeMultiplier(double value); 12 | } -------------------------------------------------------------------------------- /src/Spice86.Shared/Spice86.Shared.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Spice86.Shared 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Spice86.Shared/UI/AdditionalWindow.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Shared.UI; 2 | 3 | using Avalonia; 4 | using Avalonia.Controls; 5 | using Avalonia.Controls.ApplicationLifetimes; 6 | using Avalonia.Threading; 7 | 8 | /// 9 | /// The static class for additional windows that can be added to the UI by user code. 10 | /// 11 | public static class AdditionalWindow { 12 | /// 13 | /// Brings the window to the forefront. 14 | /// 15 | public static void Show(WindowBase window) { 16 | Dispatcher.UIThread.Post(() => { 17 | if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || desktop.MainWindow is null) { 18 | return; 19 | } 20 | if (desktop.Windows.Any(x => x == window)) { 21 | window.Activate(); 22 | } else { 23 | window.Show(); 24 | } 25 | }); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Spice86/App.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Spice86/Assets/Debug.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/src/Spice86/Assets/Debug.ico -------------------------------------------------------------------------------- /src/Spice86/Assets/RobotoMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/src/Spice86/Assets/RobotoMono-Regular.ttf -------------------------------------------------------------------------------- /src/Spice86/Assets/Spice86.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/src/Spice86/Assets/Spice86.ico -------------------------------------------------------------------------------- /src/Spice86/Controls/GroupBox.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Controls; 2 | 3 | using Avalonia.Controls.Primitives; 4 | 5 | /// 6 | /// A simple control composed of a header and content. 7 | /// 8 | internal sealed class GroupBox : HeaderedContentControl { 9 | static GroupBox() { 10 | IsTabStopProperty.OverrideDefaultValue(false); 11 | FocusableProperty.OverrideDefaultValue(false); 12 | } 13 | } -------------------------------------------------------------------------------- /src/Spice86/Controls/StatusBarItem.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Controls; 2 | 3 | using Avalonia.Controls; 4 | using Avalonia.Layout; 5 | 6 | /// 7 | /// Control that implements an item inside a StatusBar. 8 | /// 9 | internal sealed class StatusBarItem : ContentControl { 10 | static StatusBarItem() { 11 | HorizontalContentAlignmentProperty.OverrideDefaultValue(HorizontalAlignment.Stretch); 12 | IsTabStopProperty.OverrideDefaultValue(false); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Spice86/Converters/ClassToTypeStringConverter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Converters; 2 | 3 | using System.Globalization; 4 | 5 | using Avalonia.Data.Converters; 6 | 7 | internal class ClassToTypeStringConverter : IValueConverter { 8 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => value is Exception exception ? exception.GetBaseException().GetType().ToString() : value?.ToString() ?? ""; 9 | 10 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => value; 11 | } 12 | -------------------------------------------------------------------------------- /src/Spice86/Converters/NullableToBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Converters; 2 | 3 | using Avalonia.Data; 4 | using Avalonia.Data.Converters; 5 | 6 | using System.Globalization; 7 | 8 | public class NullableToBooleanConverter : IValueConverter { 9 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { 10 | return value is not null; 11 | } 12 | 13 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { 14 | return BindingOperations.DoNothing; 15 | } 16 | } -------------------------------------------------------------------------------- /src/Spice86/Infrastructure/DispatcherTimerStarter.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Infrastructure; 2 | 3 | using Avalonia.Threading; 4 | 5 | internal static class DispatcherTimerStarter { 6 | /// 7 | /// Starts a new with the specified , and . 8 | /// 9 | /// The time between executions of the callback 10 | /// The priority of execution for the UI Dispatcher 11 | /// The user code to execute 12 | public static DispatcherTimer StartNewDispatcherTimer(TimeSpan interval, DispatcherPriority priority, EventHandler callback) { 13 | var dispatcherTimer = new DispatcherTimer(interval, priority, callback); 14 | dispatcherTimer.Start(); 15 | return dispatcherTimer; 16 | } 17 | } -------------------------------------------------------------------------------- /src/Spice86/Messages/AddViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Messages; 2 | 3 | using System.ComponentModel; 4 | 5 | public record AddViewModelMessage(T ViewModel) where T : INotifyPropertyChanged; -------------------------------------------------------------------------------- /src/Spice86/Messages/AddressChangedMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Messages; 2 | public record AddressChangedMessage(uint Address); -------------------------------------------------------------------------------- /src/Spice86/Messages/RemoveViewModelMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Messages; 2 | 3 | using System.ComponentModel; 4 | 5 | public record RemoveViewModelMessage(T ViewModel) where T : INotifyPropertyChanged; -------------------------------------------------------------------------------- /src/Spice86/Messages/StatusMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Messages; 2 | 3 | public record StatusMessage(DateTime Time, object Origin, string Message); -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/CpuFlagsInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | using System.ComponentModel; 6 | 7 | public partial class CpuFlagsInfo : ObservableObject { 8 | [ObservableProperty, Category("Flags")] private bool _overflowFlag; 9 | [ObservableProperty, Category("Flags")] private bool _parityFlag; 10 | [ObservableProperty, Category("Flags")] private bool _auxiliaryFlag; 11 | [ObservableProperty, Category("Flags")] private bool _carryFlag; 12 | [ObservableProperty, Category("Flags")] private bool? _continueZeroFlag; 13 | [ObservableProperty, Category("Flags")] private bool _directionFlag; 14 | [ObservableProperty, Category("Flags")] private bool _interruptFlag; 15 | [ObservableProperty, Category("Flags")] private bool _signFlag; 16 | [ObservableProperty, Category("Flags")] private bool _trapFlag; 17 | [ObservableProperty, Category("Flags")] private bool _zeroFlag; 18 | 19 | } -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/ExceptionInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | public record ExceptionInfo(string? TargetSite, string Message, string? StackTrace); -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/FunctionInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | using Spice86.Shared.Emulator.Memory; 6 | 7 | public partial class FunctionInfo : ObservableObject { 8 | [ObservableProperty] private string? _name; 9 | [ObservableProperty] private SegmentedAddress _address; 10 | 11 | public override string ToString() { 12 | return $"{Address}: {Name}"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/MidiInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | using System.ComponentModel; 6 | 7 | public partial class MidiInfo : ObservableObject { 8 | [ObservableProperty, ReadOnly(true)] private int _lastPortRead; 9 | [ObservableProperty, ReadOnly(true)] private int _lastPortWritten; 10 | [ObservableProperty, ReadOnly(true)] private uint _lastPortWrittenValue; 11 | } -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/PortInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | using System.ComponentModel; 6 | 7 | public partial class PortInfo : ObservableObject { 8 | [ObservableProperty, ReadOnly(true)] private int _lastPortRead; 9 | [ObservableProperty, ReadOnly(true)] private int _lastPortWritten; 10 | [ObservableProperty, ReadOnly(true)] private int _lastPortWrittenValue; 11 | } -------------------------------------------------------------------------------- /src/Spice86/Models/Debugging/SoundChannelInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Models.Debugging; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | public partial class SoundChannelInfo : ObservableObject { 6 | [ObservableProperty] private int _volume; 7 | [ObservableProperty] private float _stereoSeparation; 8 | 9 | [ObservableProperty] private bool _isMuted; 10 | [ObservableProperty] private string _name = ""; 11 | } -------------------------------------------------------------------------------- /src/Spice86/UserControls/ErrorModalDialogUserControl.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace Spice86.UserControls; 4 | 5 | public partial class ErrorModalDialogUserControl : UserControl { 6 | public ErrorModalDialogUserControl() { 7 | InitializeComponent(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/Spice86/UserControls/PaletteUserControl.axaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Spice86/ViewModels/BreakpointRangeViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.ViewModels; 2 | 3 | using Spice86.Core.Emulator.VM.Breakpoint; 4 | 5 | using System; 6 | 7 | public partial class BreakpointRangeViewModel : BreakpointViewModel { 8 | public BreakpointRangeViewModel(BreakpointsViewModel breakpointsViewModel, 9 | EmulatorBreakpointsManager emulatorBreakpointsManager, long trigger, long endTrigger, 10 | BreakPointType type, bool isRemovedOnTrigger, Action onReached, 11 | string comment = "") 12 | : base(breakpointsViewModel, emulatorBreakpointsManager, trigger, type, 13 | isRemovedOnTrigger, onReached, comment) { 14 | EndTrigger = endTrigger; 15 | } 16 | 17 | public long EndTrigger { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Spice86/ViewModels/BreakpointTypeTabItemViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.ViewModels; 2 | 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | 5 | public partial class BreakpointTypeTabItemViewModel : ViewModelBase { 6 | [ObservableProperty] 7 | private string? _header; 8 | 9 | [ObservableProperty] 10 | private bool _isSelected; 11 | } 12 | -------------------------------------------------------------------------------- /src/Spice86/ViewModels/FormattedTextSegment.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.ViewModels; 2 | 3 | using Iced.Intel; 4 | 5 | /// 6 | /// Represents a segment of formatted text with its kind. 7 | /// 8 | public class FormattedTextSegment { 9 | /// 10 | /// Gets or sets the text content. 11 | /// 12 | public string Text { get; set; } = string.Empty; 13 | 14 | /// 15 | /// Gets or sets the kind of text (used for formatting). 16 | /// 17 | public FormatterTextKind Kind { get; set; } 18 | } -------------------------------------------------------------------------------- /src/Spice86/ViewModels/FormattedTextSegmentsOutput.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.ViewModels; 2 | 3 | using Iced.Intel; 4 | 5 | /// 6 | /// Thread-safe formatter output that doesn't create UI elements. 7 | /// 8 | public class FormattedTextSegmentsOutput : FormatterOutput { 9 | /// 10 | /// Gets the list of formatted text segments. 11 | /// 12 | public List Segments { get; } = []; 13 | 14 | /// 15 | /// Writes a segment of text with the specified kind. 16 | /// 17 | /// The text to write. 18 | /// The kind of text. 19 | public override void Write(string text, FormatterTextKind kind) { 20 | Segments.Add(new FormattedTextSegment { 21 | Text = text, 22 | Kind = kind 23 | }); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Spice86/ViewModels/IEmulatorObjectViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.ViewModels; 2 | using System; 3 | 4 | public interface IEmulatorObjectViewModel { 5 | public bool IsVisible { get; set; } 6 | public void UpdateValues(object? sender, EventArgs e); 7 | } 8 | -------------------------------------------------------------------------------- /src/Spice86/Views/CfgCpuView.axaml.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Views; 2 | 3 | using Avalonia.Controls; 4 | 5 | internal sealed partial class CfgCpuView : UserControl { 6 | public CfgCpuView() => InitializeComponent(); 7 | } 8 | -------------------------------------------------------------------------------- /src/Spice86/Views/DebugWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Views; 2 | 3 | using Avalonia.Controls; 4 | 5 | public sealed partial class DebugWindow : Window { 6 | public DebugWindow() { 7 | InitializeComponent(); 8 | } 9 | 10 | public DebugWindow(WindowBase owner) : this() { 11 | //Owner property has a protected setter, so we need to set it in the constructor 12 | Owner = owner; 13 | } 14 | } -------------------------------------------------------------------------------- /src/Spice86/Views/PaletteView.axaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Spice86/Views/PerformanceView.axaml.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Views; 2 | 3 | using Avalonia.Controls; 4 | 5 | internal partial class PerformanceView : UserControl { 6 | public PerformanceView() => InitializeComponent(); 7 | } 8 | -------------------------------------------------------------------------------- /src/Spice86/Views/RegistersView.axaml.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Views; 2 | 3 | using Avalonia.Controls; 4 | using Avalonia.Markup.Xaml; 5 | 6 | /// 7 | /// View for displaying CPU registers. 8 | /// 9 | public partial class RegistersView : UserControl { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public RegistersView() { 14 | InitializeComponent(); 15 | } 16 | 17 | private void InitializeComponent() { 18 | AvaloniaXamlLoader.Load(this); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Spice86/Views/SplashWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace Spice86.Views; 4 | 5 | public partial class SplashWindow : Window 6 | { 7 | public SplashWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Spice86/Views/StatusMessageView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace Spice86.Views; 6 | 7 | public partial class StatusMessageView : UserControl { 8 | public StatusMessageView() { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/Spice86/Views/StructureView.axaml.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Views; 2 | 3 | using Avalonia; 4 | using Avalonia.Controls; 5 | 6 | using Spice86.Messages; 7 | using Spice86.ViewModels; 8 | 9 | public partial class StructureView : Window { 10 | public StructureView() { 11 | InitializeComponent(); 12 | DataContextChanged += OnDataContextChanged; 13 | } 14 | 15 | private void OnDataContextChanged(object? sender, EventArgs e) { 16 | if (DataContext is StructureViewModel viewModel) { 17 | viewModel.RequestScrollToAddress += ViewModel_RequestScrollToAddress; 18 | } 19 | } 20 | 21 | private void ViewModel_RequestScrollToAddress(object? sender, AddressChangedMessage e) { 22 | var scrollOffset = new Vector(0.0, (double)e.Address / StructureHexEditor.HexView.ActualBytesPerLine); 23 | StructureHexEditor.Caret.HexView.ScrollOffset = scrollOffset; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Spice86/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Spice86/libportaudio.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/src/Spice86/libportaudio.dll -------------------------------------------------------------------------------- /tests/Spice86.Tests/CfgCpu/ModRm/TestModRmParsingContext.cs: -------------------------------------------------------------------------------- 1 | namespace Spice86.Tests.CfgCpu.ModRm; 2 | 3 | using Spice86.Core.Emulator.CPU.CfgCpu.ParsedInstruction.ModRm; 4 | using Spice86.Shared.Emulator.Memory; 5 | 6 | /// 7 | /// Implementation of for tests. 8 | /// 9 | public class TestModRmParsingContext : ModRmParsingContext { 10 | public TestModRmParsingContext(BitWidth addressWidthFromPrefixes, int? segmentOverrideFromPrefixes) { 11 | AddressWidthFromPrefixes = addressWidthFromPrefixes; 12 | SegmentOverrideFromPrefixes = segmentOverrideFromPrefixes; 13 | } 14 | public TestModRmParsingContext(BitWidth addressWidthFromPrefixes) : this(addressWidthFromPrefixes, null) { 15 | } 16 | public BitWidth AddressWidthFromPrefixes { get; } 17 | public int? SegmentOverrideFromPrefixes { get; } 18 | } -------------------------------------------------------------------------------- /tests/Spice86.Tests/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. 3 | // Project-level suppressions either have no target or are given 4 | // a specific target and scoped to a namespace, type, member, etc. 5 | 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This barely affects performance, and breaks the public APIs contract if the method is public")] 9 | [assembly: SuppressMessage("Style", "IDE0007:Use implicit type", Justification = "We don't like 'var' around these parts, partner...")] 10 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/MountPoint/drive2/folder/test.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet 2 | consectetur adipiscing elit -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/MountPoint/foo/bar/C.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet 2 | consectetur adipiscing elit -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/NativeDosTests/build.bat: -------------------------------------------------------------------------------- 1 | rem grab your Open Watcom V2 copy from https://github.com/open-watcom/open-watcom-v2/releases 2 | set WATCOM=f:\projects\fun\dos_games_rev\tools\open-watcom-2_0-c-win-x64 3 | set WATCOM_BIN=%WATCOM%\binnt64 4 | set INCLUDE=%WATCOM%\h 5 | set PATH=%WATCOM_BIN%;%PATH% 6 | 7 | wasm.exe hello.asm 8 | wlink.exe format dos file hello.obj name hello.exe 9 | 10 | wasm.exe exec.asm 11 | wlink.exe format dos file exec.obj name exec.exe 12 | 13 | wcl.exe -bt=dos c_exec.c 14 | 15 | wasm.exe tsr.asm 16 | wlink.exe format dos com file tsr.obj name tsr.com 17 | 18 | pause -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/NativeDosTests/c_exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc_, char* argv_[]) 6 | { 7 | int res = spawnl( P_WAIT, "HELLO.EXE", NULL ); 8 | printf("spawnl result: %i\n", res); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/NativeDosTests/clean.bat: -------------------------------------------------------------------------------- 1 | del c_exec.obj 2 | del exec.obj 3 | del hello.obj 4 | del tsr.obj 5 | del c_exec.exe 6 | del exec.exe 7 | del hello.exe 8 | del tsr.com 9 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/NativeDosTests/hello.asm: -------------------------------------------------------------------------------- 1 | .model small 2 | 3 | my_data_seg segment 4 | msg db 'Hello',0dh,0ah,'$' 5 | my_data_seg ends 6 | 7 | my_code_seg segment 8 | start: 9 | mov ax, my_data_seg 10 | mov ds, ax 11 | 12 | mov ah, 09h 13 | mov dx, offset msg 14 | int 21h 15 | 16 | mov ah, 4Ch 17 | int 21h 18 | my_code_seg ends 19 | 20 | my_stack_seg segment stack 21 | db 100h dup(?) 22 | my_stack_seg ends 23 | 24 | end start 25 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/NativeDosTests/readme.md: -------------------------------------------------------------------------------- 1 | # NativeDosTests 2 | some assembler and C/C++ example for several DOS APIs based on [Open Watcom V2](https://github.com/open-watcom/open-watcom-v2) toolchain 3 | | file | description | 4 | | ---- | ----------- | 5 | | build.bat | creates the DOS executables - WATCOM path variable in first line needs to be adjusted | 6 | | clean.bat | cleans up the built mess | 7 | | hello.asm | simple DOS 21h/ah=9 hello print on console | 8 | | exec.asm | DOS 21h/ax=4B00 program starter, starting hello example | 9 | | c_exec.c | same as exec but based on C stdlib | 10 | | tsr.asm | TSR that hooks DOS 21h/ah=9 and replaces 'l' with 'X' in console print - 'hello' becomes 'heXXO'| 11 | 12 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/add.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/add.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/control.asm: -------------------------------------------------------------------------------- 1 | ;1. clc 2 | ;2. cld 3 | ;3. cli 4 | ;4. cmc 5 | ;5. hlt 6 | ;6. nop 7 | ;7. stc 8 | ;8. std 9 | ;9. sti 10 | ;Memory contents at the end should be: 11 | ;00000h: d6 08 03 06 12 | 13 | 14 | use16 15 | org 0 16 | start: 17 | mov ax,1000h 18 | mov ss,ax 19 | mov sp,1000h 20 | 21 | mov cx,0feffh 22 | push cx 23 | popf 24 | 25 | clc ; (1) 26 | cld ; (2) 27 | cli ; (3) 28 | 29 | nop ; (6) 30 | 31 | pushf 32 | pop ax ; ax = 08d6h 33 | 34 | mov dx,1 35 | push dx 36 | popf 37 | 38 | cmc ; (4) 39 | stc ; (7) 40 | std ; (8) 41 | sti ; (9) 42 | 43 | pushf 44 | pop bx ; bx = 0603h 45 | 46 | mov cx,0 47 | mov ds,cx 48 | mov word [0],ax 49 | mov word [2],bx 50 | 51 | hlt ;(5) 52 | 53 | rb 65520-$ 54 | jmp start 55 | 56 | rb 65535-$ 57 | db 0ffh 58 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/selfmodifyinstructions.asm: -------------------------------------------------------------------------------- 1 | ;00: 01 00 ff ff 2 | ; compile it with fasm 3 | use16 4 | start: 5 | ; setup stack 6 | mov ax,0 7 | mov ss,ax 8 | mov sp,6 9 | ; load code 1 10 | mov si,code1 11 | loadcode: 12 | ; offset to code to load in si (source is ds:si) 13 | mov ax,word 0f000h 14 | mov ds,ax 15 | ; destination es:di 16 | mov es,ax 17 | mov di,loadarea 18 | ; size cx 19 | mov cx, word 1000 20 | rep movsw 21 | jmp loadarea 22 | 23 | rb 2048-$ 24 | code1: 25 | mov ax,word 0001h 26 | push ax 27 | ; load next 28 | mov si,code2 29 | jmp 0F000h:loadcode 30 | 31 | rb 3072-$ 32 | code2: 33 | mov bx,0001h 34 | shl bx,1 35 | push bx ;0002h 36 | ; load next 37 | mov si,code3 38 | jmp 0F000h:loadcode 39 | 40 | rb 4096-$ 41 | code3: 42 | mov cx,0001h 43 | inc cx 44 | inc cx 45 | push cx 46 | ; final test 47 | hlt 48 | 49 | rb 5120-$ 50 | loadarea: 51 | 52 | ; bios entry point at offset fff0 53 | rb 65520-$ 54 | jmp start 55 | rb 65535-$ 56 | db 0ffh 57 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/selfmodifyvalue.asm: -------------------------------------------------------------------------------- 1 | ;00: 01 00 ff ff 2 | ; compile it with fasm 3 | use16 4 | start: 5 | mov ax,0 6 | mov ss,ax 7 | mov sp,4 8 | selmodifiedmov: 9 | mov ax,0ffffh 10 | push ax 11 | mov word[cs:selmodifiedmov+1],0001h ; modify value to put in AX next time 12 | ; loop back to mov if AX is 0ffffh 13 | cmp ax,word 0ffffh 14 | je selmodifiedmov 15 | ;stack should be 0100ffff 16 | hlt 17 | 18 | ; bios entry point at offset fff0 19 | rb 65520-$ 20 | jmp start 21 | rb 65535-$ 22 | db 0ffh 23 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | *.bin 3 | *.lst 4 | *~ 5 | .dirstamp -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/AUTHORS: -------------------------------------------------------------------------------- 1 | Marco Bortolin (barotto@gmail.com) 2 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/intel-opcodes.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/intel-opcodes.ods -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/makefile: -------------------------------------------------------------------------------- 1 | all: test386 2 | 3 | test386: src/test386.asm 4 | nasm -i./src/ -f bin src/test386.asm -w-all -l test386.lst -o test386.bin 5 | 6 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/src/tests/lea_m.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Execs LEA op with 16-bit addressing and compares the result with given value 3 | ; %1 address to calculate 4 | ; %2 value to compare 5 | ; Uses: flags. 6 | ; 7 | %macro testLEA16 2 8 | push ax 9 | a16 lea ax, %1 10 | cmp ax, %2 11 | jne error 12 | pop ax 13 | %endmacro 14 | 15 | ; 16 | ; Execs LEA op with 32-bit addressing and compares the result with given value 17 | ; %1 address to calculate 18 | ; %2 value to compare 19 | ; Uses: flags. 20 | ; 21 | %macro testLEA32 2 22 | push eax 23 | a32 lea eax, %1 24 | cmp eax, %2 25 | jne error 26 | pop eax 27 | %endmacro 28 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/src/tests/load_ptr_m.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Tests LSS,LDS,LES,LFS,LGS in 16 and 32 bit mode 3 | ; %1 segment register name, one of ss,ds,es,fs,gs 4 | ; [ed:di] memory address to use for the pointer 5 | ; Uses: nothing 6 | ; 7 | 8 | %macro testLoadPtr 1 9 | mov cx, %1 10 | mov dx, es 11 | 12 | mov [es:di], word 0x1234 13 | mov [es:di + 2], word 0xabcd 14 | l%1 bx, [es:di] 15 | mov ax, %1 16 | cmp ax, 0xabcd 17 | jne error 18 | cmp bx, 0x1234 19 | jne error 20 | 21 | mov es, dx 22 | 23 | mov [es:di], dword 0x12345678 24 | mov [es:di + 4], word 0xbcde 25 | l%1 ebx, [es:di] 26 | mov ax, %1 27 | cmp ax, 0xbcde 28 | jne error 29 | cmp ebx, 0x12345678 30 | jne error 31 | 32 | mov es, dx 33 | mov %1, cx 34 | %endmacro 35 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/src/tests/paging_m.asm: -------------------------------------------------------------------------------- 1 | TESTPAGE_LIN equ 0x0049F000 ; linear test address (PDE 1, PTE 9F, offset 0) 2 | TESTPAGE_PDE equ TESTPAGE_LIN>>22 ; page directory entry 3 | TESTPAGE_PTE equ 0x2000|((TESTPAGE_LIN>>12)&0x3FF) ; page table 1 entry 4 | 5 | TESTPAGE_OFF equ (TESTPAGE_LIN&0xFFFFF) 6 | 7 | 8 | ; 9 | ; Updates the flags of a PTE 10 | ; 11 | ; %1 entry index 12 | ; %2 new flags (bits 11-0) 13 | ; 14 | ; Uses FS 15 | ; 16 | %macro updPageFlags 2 17 | pushad 18 | pushf 19 | mov eax, %1 20 | mov edx, %2 21 | call updPageFlagsP 22 | popf 23 | popad 24 | %endmacro 25 | 26 | 27 | ; 28 | ; Given a bitmask, set the value of specific PDE/PTE flags 29 | ; 30 | ; %1 entry index 31 | ; %2 flags mask 32 | ; %3 new flags value 33 | ; 34 | ; Uses FS 35 | ; 36 | %macro setPageFlags 3 37 | pushad 38 | pushf 39 | mov eax, %1 40 | mov ecx, %2 41 | mov edx, %3 42 | call setPageFlagsP 43 | popf 44 | popad 45 | %endmacro 46 | 47 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/src/tests/ver_p.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Tests for VERR and VERW instructions 3 | ; 4 | ; DX = segment selector 5 | ; BL = expected ZF value on bit 6, other bits to 0 6 | ; 7 | testVERRp: 8 | mov ah, bl 9 | not ah 10 | sahf 11 | verr dx 12 | jmp testVERresult 13 | testVERWp: 14 | mov ah, bl 15 | not ah 16 | sahf 17 | verw dx 18 | testVERresult: 19 | lahf 20 | and ah, 0x40 21 | cmp bl, ah 22 | jne error 23 | ret 24 | 25 | ; 26 | ; %1 = segment selector 27 | ; %2 = 0 or 1 (expected ZF result) 28 | ; 29 | %macro testVERR 2 30 | mov dx, %1 31 | mov bl, ((%2 & 1) << 6) 32 | call testVERRp 33 | %endmacro 34 | %macro testVERW 2 35 | mov dx, %1 36 | mov bx, ((%2 & 1) << 6) 37 | call testVERWp 38 | %endmacro 39 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/asmsrc/test386.asm/src/tests/xchg_m.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; Tests XCHG operation 3 | ; %1 dst operand 4 | ; %2 src operand 5 | ; 6 | ; Both dst and src will be overwritten. 7 | ; 8 | %macro testXchg 2 9 | %assign dst_value 0xA5A5A5A5 10 | %assign src_value 0x5A5A5A5A 11 | mov %1,dst_value 12 | mov %2,src_value 13 | xchg %1,%2 14 | cmp %1,src_value 15 | jne error 16 | cmp %2,dst_value 17 | jne error 18 | %endmacro 19 | -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/bcdcnv.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/bcdcnv.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/bitwise.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/bitwise.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/cmpneg.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/cmpneg.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/control.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/control.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/datatrnf.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/datatrnf.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/div.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/div.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/externalint.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/externalint.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/interrupt.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/interrupt.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/jmpmov.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/jmpmov.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/jump1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/jump1.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/jump2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/jump2.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/mul.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/mul.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/rep.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/rep.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/DumpedListing/control.txt: -------------------------------------------------------------------------------- 1 | F000:0000 mov AX,0x1000 2 | F000:0003 mov SS,AX 3 | F000:0005 mov SP,0x1000 4 | F000:0008 mov CX,0xFEFF 5 | F000:000B push CX 6 | F000:000C popf 7 | F000:000D clc 8 | F000:000E cld 9 | F000:000F cli 10 | F000:0010 nop 11 | F000:0011 pushf 12 | F000:0012 pop AX 13 | F000:0013 mov DX,1 14 | F000:0016 push DX 15 | F000:0017 popf 16 | F000:0018 cmc 17 | F000:0019 stc 18 | F000:001A std 19 | F000:001B sti 20 | F000:001C pushf 21 | F000:001D pop BX 22 | F000:001E mov CX,0 23 | F000:0021 mov DS,CX 24 | F000:0023 mov word ptr DS:[0],AX 25 | F000:0026 mov word ptr DS:[2],SI 26 | F000:002A hlt 27 | F000:FFF0 jmp near 0 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/DumpedListing/externalint.txt: -------------------------------------------------------------------------------- 1 | F000:0000 mov AX,0 2 | F000:0003 mov SS,AX 3 | F000:0005 mov SP,2 4 | F000:0008 mov DX,0 5 | F000:000B mov word ptr DS:[0x0020],0x003F 6 | F000:0011 mov word ptr DS:[0x0022],CS 7 | F000:0015 mov AL,0x36 8 | F000:0017 out 0x43,AL 9 | F000:0019 mov AL,0x51 10 | F000:001B out 0x40,AL 11 | F000:001D mov AL,0x22 12 | F000:001F out 0x40,AL 13 | F000:0021 mov AL,0 14 | F000:0023 out 0x21,AL 15 | F000:0025 sti 16 | F000:0026 mov ECX,0x00FFFFFF 17 | F000:002C inc AX 18 | F000:002D mov BX,BX 19 | F000:002F shr BX,1 20 | F000:0031 loop 0x002C 21 | F000:0033 cmp DX,0 22 | F000:0037 setne AL 23 | F000:003A movsz AX,AL 24 | F000:003D push AX 25 | F000:003E hlt 26 | F000:003F push AX 27 | F000:0040 mov DX,1 28 | F000:0043 mov AL,0x20 29 | F000:0045 out 0x20,AL 30 | F000:0047 pop AX 31 | F000:0048 iret 32 | F000:FFF0 jmp near 0 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/DumpedListing/selfmodifyinstructions.txt: -------------------------------------------------------------------------------- 1 | F000:0000 mov AX,0 2 | F000:0003 mov SS,AX 3 | F000:0005 mov SP,6 4 | F000:0008 mov SI,0x0800 5 | F000:000B mov AX,0xF000 6 | F000:000E mov DS,AX 7 | F000:0010 mov ES,AX 8 | F000:0012 mov DI,0x1400 9 | F000:0015 mov CX,0x03E8 10 | F000:0018 rep movs word ptr ES:[DI],word ptr DS:[SI] 11 | F000:001A jmp near 0x1400 12 | F000:1400 mov CX,1 13 | F000:1400 selector 14 | F000:1400 mov BX,1 15 | F000:1400 mov AX,1 16 | F000:1403 inc CX 17 | F000:1403 shl BX,1 18 | F000:1403 push AX 19 | F000:1404 inc CX 20 | F000:1404 mov SI,0x0C00 21 | F000:1405 push CX 22 | F000:1405 push BX 23 | F000:1406 hlt 24 | F000:1406 mov SI,0x1000 25 | F000:1407 jmp far F000:000B 26 | F000:1409 jmp far F000:000B 27 | F000:FFF0 jmp near 0 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/DumpedListing/selfmodifyvalue.txt: -------------------------------------------------------------------------------- 1 | F000:0000 mov AX,0 2 | F000:0003 mov SS,AX 3 | F000:0005 mov SP,4 4 | F000:0008 mov AX,word ptr [0x000F0009] 5 | F000:000B push AX 6 | F000:000C mov word ptr CS:[9],1 7 | F000:0013 cmp AX,0xFFFF 8 | F000:0016 je short 8 9 | F000:0018 hlt 10 | F000:FFF0 jmp near 0 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/add.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/add.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/bcdcnv.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/bcdcnv.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/bitwise.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/bitwise.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/cmpneg.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/cmpneg.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/control.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/control.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/datatrnf.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/datatrnf.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/div.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/div.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/interrupt.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/interrupt.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/jump1.bin: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/jump2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/jump2.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/mul.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/mul.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/rep.bin: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/rotate.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/rotate.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/segpr.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/segpr.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/shifts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/shifts.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/strings.bin: -------------------------------------------------------------------------------- 1 | 4 -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/sub.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/sub.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/test386.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/res/MemoryDumps/test386.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/rotate.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/rotate.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/segpr.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/segpr.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/selfmodifyinstructions.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/selfmodifyinstructions.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/selfmodifyvalue.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/selfmodifyvalue.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/shifts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/shifts.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/strings.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/strings.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/sub.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/sub.bin -------------------------------------------------------------------------------- /tests/Spice86.Tests/Resources/cpuTests/test386.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenRakis/Spice86/6fe79be499a951d7ecbc7293357b04f374fc443e/tests/Spice86.Tests/Resources/cpuTests/test386.bin --------------------------------------------------------------------------------