コード例 #1
0
        void PushLocalVariableOnToTheStack(IProgramCounter programCounter, IVariableManager localVariables)
        {
            var variableName = programCounter.GetNullTerminatedString();
            var value        = localVariables.GetVariable(variableName);

            _stack.PushValue(value);
        }
コード例 #2
0
 public bool Run(IProgramCounter programCounter, IVariableManager localVariables)
 {
     while (RunScriptCommand(programCounter, localVariables))
     {
     }
     return(programCounter.Eof);
 }
コード例 #3
0
        void SetLocalVariableToBottomValueOfStack(IProgramCounter programCounter, IVariableManager localVariables)
        {
            var value        = _stack.PopValue();
            var variableName = programCounter.GetNullTerminatedString();

            localVariables.SetVariable(variableName, value);
        }
コード例 #4
0
        void PushGlobalVariableOnToTheStack(IProgramCounter programCounter)
        {
            var variableName = programCounter.GetNullTerminatedString();
            var value        = _variableManager.GetVariable(variableName);

            _stack.PushValue(value);
        }
コード例 #5
0
        void MoveScriptPointerIfStackValueIsZero(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();

            if (_stack.PopValue() == 0)
            {
                programCounter.MoveScriptPointer(distance);
            }
        }
コード例 #6
0
        void SetUpScriptData(Action <BinaryWriter> action)
        {
            var memoryStream = new MemoryStream();
            var bw           = new BinaryWriter(memoryStream);

            action(bw);

            _programCounter = new ProgramCounter();
            _programCounter.SetScript(new SingleScript("Script Name", memoryStream.ToArray()));
        }
コード例 #7
0
        void ProcessFnRoutine(IProgramCounter programCounter, IVariableManager localVariables)
        {
            var parameterCount = programCounter.GetInteger();
            var fnRoutineName  = programCounter.GetNullTerminatedString();

            var parameters = GetStackParametersIfRequired(parameterCount);

            var result = _fnRoutinesCaller.CallFnRoutine(localVariables, fnRoutineName, parameters);

            _stack.PushValue(result);
        }
コード例 #8
0
        bool ProcessDropSkipPauseNotZero(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();
            var value    = _stack.PopValue();

            switch (value)
            {
            case (int)ScriptReturn.Continue:
                return(true);

            case (int)ScriptReturn.PauseRepeat:
                programCounter.MoveScriptPointer(distance - 4);
                return(false);

            case (int)ScriptReturn.Pause:
                return(false);
            }

            return(true);
        }
コード例 #9
0
        public Processor6502(IClock clock, IProgramCounter programCounter)
        {
            clock.OnTick    = Tick;
            _programCounter = programCounter;
            _registers      = new RegisterManager();
            _alu            = new Alu(_registers);
            _opcodes        = new Dictionary <OpCode, Action>
            {
                { OpCode.ADC_Immediate, () => _alu.ADC(Immediate()) },
                { OpCode.ADC_ZeroPage, () => _alu.ADC(ZeroPage()) },
                { OpCode.ADC_ZeroPageX, () => _alu.ADC(ZeroPageX()) },
                { OpCode.ADC_Absolute, () => _alu.ADC(Absolute()) },
                { OpCode.ADC_AbsoluteX, () => _alu.ADC(AbsoluteX()) },
                { OpCode.ADC_AbsoluteY, () => _alu.ADC(AbsoluteY()) },
                { OpCode.ADC_ZeroPageIndirectX, () => _alu.ADC(ZeroPageIndirectX()) },
                { OpCode.ADC_ZeroPageYIndirect, () => _alu.ADC(ZeroPageYIndirect()) },

                { OpCode.AND_Immediate, () => _alu.AND(Immediate()) },
                { OpCode.AND_ZeroPage, () => _alu.AND(ZeroPage()) },
                { OpCode.AND_ZeroPageX, () => _alu.AND(ZeroPageX()) },
                { OpCode.AND_Absolute, () => _alu.AND(Absolute()) },
                { OpCode.AND_AbsoluteX, () => _alu.AND(AbsoluteX()) },
                { OpCode.AND_AbsoluteY, () => _alu.AND(AbsoluteY()) },
                { OpCode.AND_ZeroPageIndirectX, () => _alu.AND(ZeroPageIndirectX()) },
                { OpCode.AND_ZeroPageYIndirect, () => _alu.AND(ZeroPageYIndirect()) },

                { OpCode.ASL, () => _registers.A = _alu.ASL(_registers.A) },
                { OpCode.ASL_ZeroPage, () => SetByte(GetNextByte(), _alu.ASL) },
                { OpCode.ASL_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.ASL) },
                { OpCode.ASL_Absolute, () => SetByte(GetUShort(), _alu.ASL) },
                { OpCode.ASL_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.ASL) },

                { OpCode.BCC, () => BranchIfNotSet(ProcessorFlags.Carry) },
                { OpCode.BCS, () => BranchIfSet(ProcessorFlags.Carry) },
                { OpCode.BNE, () => BranchIfNotSet(ProcessorFlags.Zero) },
                { OpCode.BEQ, () => BranchIfSet(ProcessorFlags.Zero) },
                { OpCode.BPL, () => BranchIfNotSet(ProcessorFlags.Negative) },
                { OpCode.BMI, () => BranchIfSet(ProcessorFlags.Negative) },
                { OpCode.BVC, () => BranchIfNotSet(ProcessorFlags.Overflow) },
                { OpCode.BVS, () => BranchIfSet(ProcessorFlags.Overflow) },
                { OpCode.BRK, BRK },
                { OpCode.CMP_Immediate, () => _alu.CMP(Immediate()) },
                { OpCode.CMP_ZeroPage, () => _alu.CMP(ZeroPage()) },
                { OpCode.CMP_ZeroPageX, () => _alu.CMP(ZeroPageX()) },
                { OpCode.CMP_Absolute, () => _alu.CMP(Absolute()) },
                { OpCode.CMP_AbsoluteX, () => _alu.CMP(AbsoluteX()) },
                { OpCode.CMP_AbsoluteY, () => _alu.CMP(AbsoluteY()) },
                { OpCode.CMP_ZeroPageIndirectX, () => _alu.CMP(ZeroPageIndirectX()) },
                { OpCode.CMP_ZeroPageYIndirect, () => _alu.CMP(ZeroPageYIndirect()) },

                { OpCode.CPX_Immediate, () => _alu.CPX(Immediate()) },
                { OpCode.CPX_ZeroPage, () => _alu.CPX(ZeroPage()) },
                { OpCode.CPX_Absolute, () => _alu.CPX(Absolute()) },

                { OpCode.CPY_Immediate, () => _alu.CPY(Immediate()) },
                { OpCode.CPY_ZeroPage, () => _alu.CPY(ZeroPage()) },
                { OpCode.CPY_Absolute, () => _alu.CPY(Absolute()) },

                { OpCode.CLC, () => _registers.Status &= ~ProcessorFlags.Carry },
                { OpCode.CLD, () => _registers.Status &= ~ProcessorFlags.Decimal },
                { OpCode.CLI, () => _registers.Status &= ~ProcessorFlags.InterruptDisable },
                { OpCode.CLV, () => _registers.Status &= ~ProcessorFlags.Overflow },

                { OpCode.DEC_ZeroPage, () => SetByte(GetNextByte(), _alu.DEC) },
                { OpCode.DEC_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.DEC) },
                { OpCode.DEC_Absolute, () => SetByte(GetUShort(), _alu.DEC) },
                { OpCode.DEC_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.DEC) },

                { OpCode.DEX, () => _registers.X = _alu.DEC(_registers.X) },
                { OpCode.DEY, () => _registers.Y = _alu.DEC(_registers.Y) },

                { OpCode.EOR_Immediate, () => _alu.EOR(Immediate()) },
                { OpCode.EOR_ZeroPage, () => _alu.EOR(ZeroPage()) },
                { OpCode.EOR_ZeroPageX, () => _alu.EOR(ZeroPageX()) },
                { OpCode.EOR_Absolute, () => _alu.EOR(Absolute()) },
                { OpCode.EOR_AbsoluteX, () => _alu.EOR(AbsoluteX()) },
                { OpCode.EOR_AbsoluteY, () => _alu.EOR(AbsoluteY()) },
                { OpCode.EOR_ZeroPageIndirectX, () => _alu.EOR(ZeroPageIndirectX()) },
                { OpCode.EOR_ZeroPageYIndirect, () => _alu.EOR(ZeroPageYIndirect()) },

                { OpCode.INC_ZeroPage, () => SetByte(GetNextByte(), _alu.INC) },
                { OpCode.INC_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.INC) },
                { OpCode.INC_Absolute, () => SetByte(GetUShort(), _alu.INC) },
                { OpCode.INC_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.INC) },

                { OpCode.INX, () => _registers.X = _alu.INC(_registers.X) },
                { OpCode.INY, () => _registers.Y = _alu.INC(_registers.Y) },

                { OpCode.JMP_Absolute, () => _programCounter.Set(GetUShort()) },
                { OpCode.JMP_Indirect, () => _programCounter.Set(GetUShort(GetUShort())) },
                { OpCode.JSR, () => JSR() },

                { OpCode.LDA_Immediate, () => _alu.LDA(Immediate()) },
                { OpCode.LDA_ZeroPage, () => _alu.LDA(ZeroPage()) },
                { OpCode.LDA_ZeroPageX, () => _alu.LDA(ZeroPageX()) },
                { OpCode.LDA_Absolute, () => _alu.LDA(Absolute()) },
                { OpCode.LDA_AbsoluteX, () => _alu.LDA(AbsoluteX()) },
                { OpCode.LDA_AbsoluteY, () => _alu.LDA(AbsoluteY()) },
                { OpCode.LDA_ZeroPageIndirectX, () => _alu.LDA(ZeroPageIndirectX()) },
                { OpCode.LDA_ZeroPageYIndirect, () => _alu.LDA(ZeroPageYIndirect()) },

                { OpCode.LDX_Immediate, () => _alu.LDX(Immediate()) },
                { OpCode.LDX_ZeroPage, () => _alu.LDX(ZeroPage()) },
                { OpCode.LDX_ZeroPageY, () => _alu.LDX(GetByte(GetNextByte(), _registers.Y)) },
                { OpCode.LDX_Absolute, () => _alu.LDX(Absolute()) },
                { OpCode.LDX_AbsoluteY, () => _alu.LDX(AbsoluteY()) },

                { OpCode.LDY_Immediate, () => _alu.LDY(Immediate()) },
                { OpCode.LDY_ZeroPage, () => _alu.LDY(ZeroPage()) },
                { OpCode.LDY_ZeroPageX, () => _alu.LDY(ZeroPageX()) },
                { OpCode.LDY_Absolute, () => _alu.LDY(Absolute()) },
                { OpCode.LDY_AbsoluteX, () => _alu.LDY(AbsoluteX()) },

                { OpCode.LSR, () => _registers.A = _alu.LSR(_registers.A) },
                { OpCode.LSR_ZeroPage, () => SetByte(GetNextByte(), _alu.LSR) },
                { OpCode.LSR_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.LSR) },
                { OpCode.LSR_Absolute, () => SetByte(GetUShort(), _alu.LSR) },
                { OpCode.LSR_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.LSR) },

                { OpCode.NOP, () => { } },

                { OpCode.ORA_Immediate, () => _alu.ORA(Immediate()) },
                { OpCode.ORA_ZeroPage, () => _alu.ORA(ZeroPage()) },
                { OpCode.ORA_ZeroPageX, () => _alu.ORA(ZeroPageX()) },
                { OpCode.ORA_Absolute, () => _alu.ORA(Absolute()) },
                { OpCode.ORA_AbsoluteX, () => _alu.ORA(AbsoluteX()) },
                { OpCode.ORA_AbsoluteY, () => _alu.ORA(AbsoluteY()) },
                { OpCode.ORA_ZeroPageIndirectX, () => _alu.ORA(ZeroPageIndirectX()) },
                { OpCode.ORA_ZeroPageYIndirect, () => _alu.ORA(ZeroPageYIndirect()) },

                { OpCode.PHA, () => Push(_registers.A) },
                { OpCode.PLA, () => _registers.A = Pull() },
                { OpCode.PHP, () => Push((byte)_registers.Status) },
                { OpCode.PLP, () => _registers.Status = (ProcessorFlags)Pull() },

                { OpCode.ROL, () => _registers.A = _alu.ROL(_registers.A) },
                { OpCode.ROL_ZeroPage, () => SetByte(GetNextByte(), _alu.ROL) },
                { OpCode.ROL_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.ROL) },
                { OpCode.ROL_Absolute, () => SetByte(GetUShort(), _alu.ROL) },
                { OpCode.ROL_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.ROL) },

                { OpCode.ROR, () => _registers.A = _alu.ROR(_registers.A) },
                { OpCode.ROR_ZeroPage, () => SetByte(GetNextByte(), _alu.ROR) },
                { OpCode.ROR_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, _alu.ROR) },
                { OpCode.ROR_Absolute, () => SetByte(GetUShort(), _alu.ROR) },
                { OpCode.ROR_AbsoluteX, () => SetByte(GetUShort(), _registers.X, _alu.ROR) },

                { OpCode.RTS, RTS },
                { OpCode.RTI, RTI },

                { OpCode.SBC_Immediate, () => _alu.SBC(Immediate()) },
                { OpCode.SBC_ZeroPage, () => _alu.SBC(ZeroPage()) },
                { OpCode.SBC_ZeroPageX, () => _alu.SBC(ZeroPageX()) },
                { OpCode.SBC_Absolute, () => _alu.SBC(Absolute()) },
                { OpCode.SBC_AbsoluteX, () => _alu.SBC(AbsoluteX()) },
                { OpCode.SBC_AbsoluteY, () => _alu.SBC(AbsoluteY()) },
                { OpCode.SBC_ZeroPageIndirectX, () => _alu.SBC(ZeroPageIndirectX()) },
                { OpCode.SBC_ZeroPageYIndirect, () => _alu.SBC(ZeroPageYIndirect()) },

                { OpCode.SEC, () => _registers.Status |= ProcessorFlags.Carry },
                { OpCode.SED, () => _registers.Status |= ProcessorFlags.Decimal },
                { OpCode.SEI, () => _registers.Status |= ProcessorFlags.InterruptDisable },

                { OpCode.STA_ZeroPage, () => SetByte(GetNextByte(), v => _registers.A) },
                { OpCode.STA_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, v => _registers.A) },
                { OpCode.STA_Absolute, () => SetByte(GetUShort(), v => _registers.A) },
                { OpCode.STA_AbsoluteX, () => SetByte(GetUShort(), _registers.X, v => _registers.A) },
                { OpCode.STA_AbsoluteY, () => SetByte(GetUShort(), _registers.Y, v => _registers.A) },
                { OpCode.STA_ZeroPageIndirectX, () => SetByte(GetUShort(GetNextByte(_registers.X)), v => _registers.A) },
                { OpCode.STA_ZeroPageYIndirect, () => SetByte(GetUShort(GetNextByte()), _registers.Y, v => _registers.A) },
                { OpCode.STX_ZeroPage, () => SetByte(GetNextByte(), v => _registers.X) },
                { OpCode.STX_ZeroPageY, () => SetByte(GetNextByte(), _registers.Y, v => _registers.X) },
                { OpCode.STX_Absolute, () => SetByte(GetUShort(), v => _registers.X) },
                { OpCode.STY_ZeroPage, () => SetByte(GetNextByte(), v => _registers.Y) },
                { OpCode.STY_ZeroPageX, () => SetByte(GetNextByte(), _registers.X, v => _registers.Y) },
                { OpCode.STY_Absolute, () => SetByte(GetUShort(), v => _registers.Y) },

                { OpCode.TAX, () => _alu.TAX() },
                { OpCode.TAY, () => _alu.TAY() },
                { OpCode.TSX, () => _registers.X = _stackPointer },
                { OpCode.TXA, () => _alu.TXA() },
                { OpCode.TXS, () => _stackPointer = _registers.X },
                { OpCode.TYA, () => _alu.TYA() },
            };
        }
コード例 #10
0
        bool RunScriptCommand(IProgramCounter programCounter, IVariableManager localVariables)
        {
            if (programCounter.Eof)
            {
                throw new Exception($"Unexpected end of script found in '{programCounter.GetScriptName()}'");
            }

            var command = programCounter.GetCommand();

            switch ((ScriptToken)command)
            {
            case ScriptToken.PushIntValue:
                _stack.PushValue(programCounter.GetInteger());
                break;

            case ScriptToken.PushStringValue:
                _stack.PushValue(programCounter.GetNullTerminatedString());
                break;

            case ScriptToken.PushGlobalVariable:     //  4
                PushGlobalVariableOnToTheStack(programCounter);
                break;

            case ScriptToken.PopGlobalVariable:     //  5
                SetGlobalVariableToBottomValueOfStack(programCounter);
                break;

            case ScriptToken.Jfalse:     //  6
                MoveScriptPointerIfStackValueIsZero(programCounter);
                break;

            case ScriptToken.Jtrue:     //  7
                MoveScriptPointerIfStackValueIsNotZero(programCounter);
                break;

            case ScriptToken.Jall:     //  8
                MoveScriptPointerAlways(programCounter);
                break;

            case ScriptToken.Add:     //  9
                _stack.Add();
                break;

            case ScriptToken.Subtract:     //  10
                _stack.Subtract();
                break;

            case ScriptToken.Multiply:     //  11
                _stack.Multiply();
                break;

            case ScriptToken.Divide:     //  12
                _stack.Divide();
                break;

            case ScriptToken.Negate:     //  13
                _stack.Negate();
                break;

            case ScriptToken.LogicalNot:     //  14
                _stack.LogicalNot();
                break;

            case ScriptToken.Lt:     //  15
                _stack.Lt();
                break;

            case ScriptToken.Gt:     //  16
                _stack.Gt();
                break;

            case ScriptToken.Lte:     //  17
                _stack.Lte();
                break;

            case ScriptToken.Gte:     //  18
                _stack.Gte();
                break;

            case ScriptToken.VariableEquals:     //  19
                _stack.VariableEquals();
                break;

            case ScriptToken.LogicalAnd:     //  20
                _stack.LogicalAnd();
                break;

            case ScriptToken.LogicalOr:     //  21
                _stack.LogicalOr();
                break;

            case ScriptToken.CallFnRoutine:     //  22
                ProcessFnRoutine(programCounter, localVariables);
                break;

            case ScriptToken.DropStackValue:     //  23
                return(_stack.PopValue() == 0);

            case ScriptToken.EndScript:     //  24
                return(false);

            case ScriptToken.DropSkipPauseNotZero:     //  25
                return(ProcessDropSkipPauseNotZero(programCounter));

            case ScriptToken.PauseScript:     // 26
                return(false);

            case ScriptToken.PushLocalVariable:     //  27
                PushLocalVariableOnToTheStack(programCounter, localVariables);
                break;

            case ScriptToken.PopLocalVariable:     //  28
                SetLocalVariableToBottomValueOfStack(programCounter, localVariables);
                break;

            default:
                throw new InvalidOperationException($"Invalid Script Command {command}");
            }

            return(true);
        }
コード例 #11
0
        void MoveScriptPointerAlways(IProgramCounter programCounter)
        {
            var distance = programCounter.GetInteger();

            programCounter.MoveScriptPointer(distance);
        }