예제 #1
0
        private void MoveToNextHalfWord()
        {
            if (_immediateHalf == ImmediateHalf.Second)
            {
                _pc++;
                _immediateWord = _mem.Fetch(_pc);
                _immediateHalf = ImmediateHalf.First;

                // Update the instruction cache with the type of instruction (to aid in debugging).
                PDS1DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.Increment);
            }
            else
            {
                _immediateHalf = ImmediateHalf.Second;
            }
        }
예제 #2
0
 public override void InitializeCache()
 {
     _instructionCache = new PDS1DisplayInstruction[Memory.Size];
 }
예제 #3
0
        private void ExecuteProcessor()
        {
            PDS1DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.Processor);

            instruction.UsageMode = DisplayProcessorMode.Processor;

            switch (instruction.Opcode)
            {
            case DisplayOpcode.DEIM:
                _mode          = DisplayProcessorMode.Increment;
                _immediateWord = instruction.Data;
                _immediateHalf = ImmediateHalf.Second;
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.DisplayProcessor, "Enter increment mode");
                }
                break;

            case DisplayOpcode.DJMP:
                if (!_dadr)
                {
                    // DADR off, use only 12 bits
                    _pc = (ushort)((instruction.Data & 0xfff) | _block);
                }
                else
                {
                    _pc = (ushort)(instruction.Data | _block);
                }
                break;

            case DisplayOpcode.DJMS:
                Push();

                if (!_dadr)
                {
                    // DADR off, use only 12 bits
                    _pc = (ushort)((instruction.Data & 0xfff) | _block);
                }
                else
                {
                    _pc = (ushort)(instruction.Data | _block);
                }
                break;

            case DisplayOpcode.DOPR:
                // Each of bits 4-11 can be combined in any fashion
                // to do a number of operations simultaneously; we walk the bits
                // and perform the operations as set.
                if ((instruction.Data & 0x800) == 0)
                {
                    // DHLT -- halt the display processor.  other micro-ops in this
                    // instruction are still run.
                    HaltProcessor();
                }

                if ((instruction.Data & 0x400) != 0)
                {
                    // HV Sync; this is currently a no-op, not much to do in emulation.
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "HV Sync");
                    }

                    _system.Display.MoveAbsolute(X, Y, DrawingMode.Off);
                }

                if ((instruction.Data & 0x200) != 0)
                {
                    // DIXM -- increment X DAC MSB
                    X += 0x20;
                    _system.Display.MoveAbsolute(X, Y, DrawingMode.Off);
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "DIXM, X is now {0}", X);
                    }
                }

                if ((instruction.Data & 0x100) != 0)
                {
                    // DIYM -- increment Y DAC MSB
                    Y += 0x20;
                    _system.Display.MoveAbsolute(X, Y, DrawingMode.Off);
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "DIYM, Y is now {0}", Y);
                    }
                }

                if ((instruction.Data & 0x80) != 0)
                {
                    // DDXM - decrement X DAC MSB
                    X -= 0x20;
                    _system.Display.MoveAbsolute(X, Y, DrawingMode.Off);
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "DDXM, X is now {0}", X);
                    }
                }

                if ((instruction.Data & 0x40) != 0)
                {
                    // DDYM - decrement y DAC MSB
                    Y -= 0x20;
                    _system.Display.MoveAbsolute(X, Y, DrawingMode.Off);
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "DDYM, Y is now {0}", Y);
                    }
                }

                if ((instruction.Data & 0x20) != 0)
                {
                    // DRJM - return from display subroutine
                    ReturnFromDisplaySubroutine();
                    _pc--;      // hack (we add +1 at the end...)
                }

                if ((instruction.Data & 0x10) != 0)
                {
                    // DDSP -- intensify point on screen for 1.8us (one instruction)
                    // at the current position.
                    _system.Display.DrawPoint(X, Y);

                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "DDSP at {0},{1}", X, Y);
                    }
                }

                // F/C ops:
                int f = (instruction.Data & 0xc) >> 2;
                int c = instruction.Data & 0x3;

                switch (f)
                {
                case 0x0:
                    // if bit 15 is set, the MIT mods flip the DADR bit.
                    if (Configuration.MITMode && (c == 1))
                    {
                        _dadr = !_dadr;
                    }
                    break;

                case 0x1:
                    // Set scale based on C
                    switch (c)
                    {
                    case 0:
                        _scale = 1.0f;
                        break;

                    default:
                        _scale = c;
                        break;
                    }
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "Scale set to {0}", _scale);
                    }
                    break;

                case 0x2:
                    if (!Configuration.MITMode)
                    {
                        _block = (ushort)(c << 12);
                    }
                    break;

                case 0x3:
                    // TODO: light pen sensitize
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "Light pen, stub!");
                    }
                    break;
                }

                _pc++;
                break;

            case DisplayOpcode.DLXA:
                X = instruction.Data << 1;

                DrawingMode mode;
                if (_sgrModeOn && _sgrBeamOn)
                {
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "SGR-1 X set to {0}", X);
                    }
                    mode = DrawingMode.SGR1;
                }
                else
                {
                    mode = DrawingMode.Off;
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "X set to {0}", X);
                    }
                }

                _system.Display.MoveAbsolute(X, Y, mode);

                if (_sgrDJRMOn)
                {
                    ReturnFromDisplaySubroutine();
                }
                else
                {
                    _pc++;
                }
                break;

            case DisplayOpcode.DLYA:
                Y = instruction.Data << 1;

                if (_sgrModeOn && _sgrBeamOn)
                {
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "SGR-1 Y set to {0}", Y);
                    }
                    mode = DrawingMode.SGR1;
                }
                else
                {
                    if (Trace.TraceOn)
                    {
                        Trace.Log(LogType.DisplayProcessor, "Y set to {0}", Y);
                    }
                    mode = DrawingMode.Off;
                }

                _system.Display.MoveAbsolute(X, Y, mode);

                if (_sgrDJRMOn)
                {
                    ReturnFromDisplaySubroutine();
                }
                else
                {
                    _pc++;
                }
                break;

            case DisplayOpcode.DLVH:
                DrawLongVector(instruction.Data);
                break;

            case DisplayOpcode.SGR1:
                _sgrModeOn = (instruction.Data & 0x1) != 0;
                _sgrDJRMOn = (instruction.Data & 0x2) != 0;
                _sgrBeamOn = (instruction.Data & 0x4) != 0;

                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.DisplayProcessor, "SGR-1 instruction: Enter {0} BeamOn {1} DRJM {2}", _sgrModeOn, _sgrBeamOn, _sgrDJRMOn);
                }
                _pc++;
                break;

            default:
                throw new NotImplementedException(String.Format("Unimplemented Display Processor Opcode {0}, operands {1}", Helpers.ToOctal((ushort)instruction.Opcode), Helpers.ToOctal(instruction.Data)));
            }

            // If the next instruction has a breakpoint set we'll halt at this point, before executing it.
            if (BreakpointManager.TestBreakpoint(BreakpointType.Display, _pc))
            {
                _state = ProcessorState.BreakpointHalt;
            }
        }