├── .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
--------------------------------------------------------------------------------