Example #1
0
        private void MoveToNextCAMHalfWord()
        {
            if (_camHalf == ImmediateHalf.Second)
            {
                _pc++;
                _camWord = _mem.Fetch(_pc);
                _camHalf = ImmediateHalf.First;

                // Update the instruction cache with the type of instruction (to aid in debugging).
                PDS4DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.CompactAddressing);
            }
            else
            {
                _camHalf = ImmediateHalf.Second;
            }
        }
Example #2
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).
                PDS4DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.Increment);
            }
            else
            {
                _immediateHalf = ImmediateHalf.Second;
            }
        }
Example #3
0
 public override void InitializeCache()
 {
     _instructionCache = new PDS4DisplayInstruction[Memory.Size];
 }
Example #4
0
        private void ExecuteProcessor()
        {
            PDS4DisplayInstruction 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();
                }

                // Used to modify DSTS or DSTB operation
                bool bit5 = (instruction.Data & 0x400) != 0;

                if ((instruction.Data & 0x200) != 0)
                {
                    // DIXM -- increment X DAC MSB
                    X += MSBIncrement;
                    _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 += MSBIncrement;
                    _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 -= MSBIncrement;
                    _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 -= MSBIncrement;
                    _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 and Bit 5.
                    _scale = c + (bit5 ? 4 : 0);

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

                case 0x2:
                    _block = (ushort)((c + (bit5 ? 4 : 0) << 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;

                DrawingMode mode;
                if (_fxyOn && _fxyBeamOn)
                {
                    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 (_fxyDRJMOn)
                {
                    ReturnFromDisplaySubroutine();
                }
                else
                {
                    _pc++;
                }
                break;

            case DisplayOpcode.DLYA:
                Y = instruction.Data;

                if (_fxyOn && _fxyBeamOn)
                {
                    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 (_fxyDRJMOn)
                {
                    ReturnFromDisplaySubroutine();
                }
                else
                {
                    _pc++;
                }
                break;

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

            case DisplayOpcode.DFXY:
                _fxyOn     = (instruction.Data & 0x1) != 0;
                _fxyDRJMOn = (instruction.Data & 0x2) != 0;
                _fxyBeamOn = (instruction.Data & 0x4) != 0;

                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.DisplayProcessor, "SGR-1 instruction: Enter {0} BeamOn {1} DRJM {2}",
                              _fxyOn,
                              _fxyBeamOn,
                              _fxyDRJMOn);
                }

                _pc++;
                break;

            case DisplayOpcode.DVIC:
                _system.Display.SetIntensity(instruction.Data);
                _pc++;
                break;

            case DisplayOpcode.DCAM:
                // Enter Compact Addressing Mode, this is supposedly illegal if
                // we're already in that mode, so we'll throw here to help with debugging
                if (_camEnabled)
                {
                    throw new InvalidOperationException("DCAM while in Compact Addressing Mode.");
                }

                _camEnabled = true;

                // subroutine table address is the next word.  Low 8-bits should be zero, we'll
                // sanity check it.
                _caBase = _mem.Fetch(++_pc);

                if ((_caBase & 0xff) != 0)
                {
                    throw new InvalidOperationException(
                              String.Format("CAM subroutine base address {0} not on a 256-word boundary!",
                                            Helpers.ToOctal(_caBase)));
                }

                // start things off by fetching the first subroutine word.  This is not strictly
                // accurate with respect to timing.  (Ok, it's not accurate at all.)
                // TODO: refactor Immediate halfword routines here (share w/short vectors?)
                _camWord = _mem.Fetch(++_pc);
                _camHalf = ImmediateHalf.First;
                if (Trace.TraceOn)
                {
                    Trace.Log(LogType.DisplayProcessor, "Enter Compact Addressing mode, base address {0}",
                              Helpers.ToOctal(_caBase));
                }

                _mode = DisplayProcessorMode.CompactAddressing;
                break;

            case DisplayOpcode.DBLI:
                _system.Display.SetBlink((instruction.Data) != 0);
                _pc++;
                break;

            default:
                throw new NotImplementedException(String.Format("Unimplemented Display Processor Opcode {0}, ({1}), operands {1}",
                                                                instruction.Opcode,
                                                                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;
            }
        }