Exemple #1
0
        /// <summary>
        /// Computes the next machine frame, updating contents of the provided <see cref="FrameBuffer"/>.
        /// </summary>
        /// <param name="frameBuffer">The framebuffer to contain the computed output.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException">frameBuffer is incompatible with machine.</exception>
        public virtual void ComputeNextFrame(FrameBuffer frameBuffer)
        {
            if (MachineHalt)
            {
                return;
            }

            InputState.CaptureInputState();

            _FrameBuffer = frameBuffer;
            FrameNumber++;

            for (var i = 0; i < _FrameBuffer.SoundBufferByteLength; i++)
            {
                _FrameBuffer.SoundBuffer[i] = 0;
            }
        }
 public override void ComputeNextFrame(FrameBuffer frameBuffer)
 {
     base.ComputeNextFrame(frameBuffer);
     TIA.StartFrame();
     CPU.RunClocks = (FrameBuffer.Scanlines + 3) * 76;
     while (CPU.RunClocks > 0 && !CPU.Jammed)
     {
         if (TIA.WSYNCDelayClocks > 0)
         {
             CPU.Clock           += (ulong)TIA.WSYNCDelayClocks / 3;
             CPU.RunClocks       -= TIA.WSYNCDelayClocks / 3;
             TIA.WSYNCDelayClocks = 0;
         }
         if (TIA.EndOfFrame)
         {
             break;
         }
         CPU.Execute();
     }
     TIA.EndFrame();
 }
Exemple #3
0
 /// <summary>
 /// Create a <see cref="FrameBuffer"/> with compatible dimensions for this machine.
 /// </summary>
 public FrameBuffer CreateFrameBuffer()
 {
     var fb = new FrameBuffer(_VisiblePitch, _Scanlines);
     return fb;
 }
Exemple #4
0
        /// <summary>
        /// Computes the next machine frame, updating contents of the provided <see cref="FrameBuffer"/>.
        /// </summary>
        /// <param name="frameBuffer">The framebuffer to contain the computed output.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException">frameBuffer is incompatible with machine.</exception>
        public virtual void ComputeNextFrame(FrameBuffer frameBuffer)
        {
            if (MachineHalt)
                return;

            InputState.CaptureInputState();

            _FrameBuffer = frameBuffer;
            FrameNumber++;

			for (var i = 0; i < _FrameBuffer.SoundBufferByteLength; i++)
				_FrameBuffer.SoundBuffer[i] = 0;
        }
Exemple #5
0
			public void ConnectToMachine(MachineBase m, EMU7800.Win.GameProgram g)
			{
				framebuffer = m.CreateFrameBuffer();
				BufferWidth = framebuffer.VisiblePitch;
				BufferHeight = framebuffer.Scanlines;
				vidbuffer = new int[BufferWidth * BufferHeight];

				uint newsamplerate = (uint)m.SoundSampleFrequency;
				if (newsamplerate != samplerate)
				{
					// really shouldn't happen (after init), but if it does, we're ready
					if (resampler != null)
						resampler.Dispose();
					resampler = new SpeexResampler(3, newsamplerate, 44100, newsamplerate, 44100, null, null);
					samplerate = newsamplerate;
					dcfilter = DCFilter.DetatchedMode(256);
				}
				if (g.MachineType == MachineType.A7800PAL || g.MachineType == MachineType.A2600PAL)
					palette = TIATables.PALPalette;
				else
					palette = TIATables.NTSCPalette;
			}
Exemple #6
0
        /// <summary>
        /// Draw specified text at specified position using the specified foreground and background colors.
        /// </summary>
        /// <param name="frameBuffer"></param>
        /// <param name="text"></param>
        /// <param name="xoffset"></param>
        /// <param name="yoffset"></param>
        /// <param name="fore"></param>
        /// <param name="back"></param>
        /// <exception cref="ArgumentNullException">text must be non-null.</exception>
        public void DrawText(FrameBuffer frameBuffer, string text, int xoffset, int yoffset, byte fore, byte back)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text");
            }

            var textchars = text.ToUpper().ToCharArray();

            for (var i = 0; i < text.Length + 1; i++)
            {
                for (var j = 0; j < 9; j++)
                {
                    var pos = (j + yoffset) * frameBuffer.VisiblePitch + i * 5;
                    for (var k = 0; k < 5; k++)
                    {
                        while (pos >= frameBuffer.VideoBufferByteLength)
                        {
                            pos -= frameBuffer.VideoBufferByteLength;
                        }
                        while (pos < 0)
                        {
                            pos += frameBuffer.VideoBufferByteLength;
                        }
                        frameBuffer.VideoBuffer[pos++] = back;
                    }
                }
            }

            for (var i = 0; i < text.Length; i++)
            {
                var  c = textchars[i];
                uint fdata;

                switch (c)
                {
                case '/':
                case '\\':
                    fdata = 0x0122448;
                    break;

                case '(':
                    fdata = 0x2488842;
                    break;

                case ')':
                    fdata = 0x4211124;
                    break;

                case '.':
                    fdata = 0x0000066;
                    break;

                case ':':
                    fdata = 0x0660660;
                    break;

                case '-':
                    fdata = 0x0007000;
                    break;

                default:
                    if (c >= 'A' && c <= 'Z')
                    {
                        fdata = AlphaFontData[c - 'A'];
                    }
                    else if (c >= '0' && c <= '9')
                    {
                        fdata = DigitFontData[c - '0'];
                    }
                    else
                    {
                        fdata = 0;
                    }
                    break;
                }

                var ypos = 8;
                for (var j = 0; j < 32; j++)
                {
                    var xpos = j & 3;
                    if (xpos == 0)
                    {
                        ypos--;
                    }

                    var pos = (ypos + yoffset) * frameBuffer.VisiblePitch + (4 - xpos) + xoffset;
                    while (pos >= frameBuffer.VideoBufferByteLength)
                    {
                        pos -= frameBuffer.VideoBufferByteLength;
                    }
                    while (pos < 0)
                    {
                        pos += frameBuffer.VideoBufferByteLength;
                    }
                    if (((fdata >> j) & 1) != 0)
                    {
                        frameBuffer.VideoBuffer[pos] = fore;
                    }
                }
                xoffset += 5;
            }
        }
Exemple #7
0
        /// <summary>
        /// Draw specified text at specified position using the specified foreground and background colors.
        /// </summary>
        /// <param name="frameBuffer"></param>
        /// <param name="text"></param>
        /// <param name="xoffset"></param>
        /// <param name="yoffset"></param>
        /// <param name="fore"></param>
        /// <param name="back"></param>
        /// <exception cref="ArgumentNullException">text must be non-null.</exception>
        public void DrawText(FrameBuffer frameBuffer, string text, int xoffset, int yoffset, byte fore, byte back)
        {
            if (text == null)
                throw new ArgumentNullException("text");

            var textchars = text.ToUpper().ToCharArray();

            for (var i = 0; i < text.Length + 1; i++)
            {
                for (var j = 0; j < 9; j++)
                {
                    var pos = (j + yoffset) * frameBuffer.VisiblePitch + i * 5;
                    for (var k = 0; k < 5; k++)
                    {
                        while (pos >= frameBuffer.VideoBufferByteLength)
                        {
                            pos -= frameBuffer.VideoBufferByteLength;
                        }
                        while (pos < 0)
                        {
                            pos += frameBuffer.VideoBufferByteLength;
                        }
                        frameBuffer.VideoBuffer[pos++] = back;
                    }
                }
            }

            for (var i = 0; i < text.Length; i++)
            {
                var c = textchars[i];
                uint fdata;

                switch (c)
                {
                    case '/':
                    case '\\':
                        fdata = 0x0122448;
                        break;
                    case '(':
                        fdata = 0x2488842;
                        break;
                    case ')':
                        fdata = 0x4211124;
                        break;
                    case '.':
                        fdata = 0x0000066;
                        break;
                    case ':':
                        fdata = 0x0660660;
                        break;
                    case '-':
                        fdata = 0x0007000;
                        break;
                    default:
                        if (c >= 'A' && c <= 'Z')
                        {
                            fdata = AlphaFontData[c - 'A'];
                        }
                        else if (c >= '0' && c <= '9')
                        {
                            fdata = DigitFontData[c - '0'];
                        }
                        else
                        {
                            fdata = 0;
                        }
                        break;
                }

                var ypos = 8;
                for (var j = 0; j < 32; j++)
                {
                    var xpos = j & 3;
                    if (xpos == 0)
                    {
                        ypos--;
                    }

                    var pos = (ypos + yoffset) * frameBuffer.VisiblePitch + (4 - xpos) + xoffset;
                    while (pos >= frameBuffer.VideoBufferByteLength)
                    {
                        pos -= frameBuffer.VideoBufferByteLength;
                    }
                    while (pos < 0)
                    {
                        pos += frameBuffer.VideoBufferByteLength;
                    }
                    if (((fdata >> j) & 1) != 0)
                    {
                        frameBuffer.VideoBuffer[pos] = fore;
                    }
                }
                xoffset += 5;
            }
        }
Exemple #8
0
        /// <summary>
        /// Create a <see cref="FrameBuffer"/> with compatible dimensions for this machine.
        /// </summary>
        public FrameBuffer CreateFrameBuffer()
        {
            var fb = new FrameBuffer(_VisiblePitch, _Scanlines);

            return(fb);
        }
        public override void ComputeNextFrame(FrameBuffer frameBuffer)
        {
            base.ComputeNextFrame(frameBuffer);

            AssertDebug(CPU.Jammed || CPU.RunClocks <= 0 && (CPU.RunClocks % CPU.RunClocksMultiple) == 0);
            AssertDebug(CPU.Jammed || ((CPU.Clock + (ulong)(CPU.RunClocks / CPU.RunClocksMultiple)) % (114 * (ulong)FrameBuffer.Scanlines)) == 0);

            ulong startOfScanlineCpuClock = 0;

            Maria.StartFrame();
            Cart.StartFrame();
            for (var i = 0; i < FrameBuffer.Scanlines && !CPU.Jammed; i++)
            {
                AssertDebug(CPU.RunClocks <= 0 && (CPU.RunClocks % CPU.RunClocksMultiple) == 0);
                var newStartOfScanlineCpuClock = CPU.Clock + (ulong)(CPU.RunClocks / CPU.RunClocksMultiple);

                AssertDebug(startOfScanlineCpuClock == 0 || newStartOfScanlineCpuClock == startOfScanlineCpuClock + 114);
                startOfScanlineCpuClock = newStartOfScanlineCpuClock;

                CPU.RunClocks += (7 * CPU.RunClocksMultiple);
                var remainingRunClocks = (114 - 7) * CPU.RunClocksMultiple;

                CPU.Execute();
                if (CPU.Jammed)
                {
                    break;
                }
                if (CPU.EmulatorPreemptRequest)
                {
                    Maria.DoDMAProcessing();
                    var remainingCpuClocks = 114 - (CPU.Clock - startOfScanlineCpuClock);
                    CPU.Clock    += remainingCpuClocks;
                    CPU.RunClocks = 0;
                    continue;
                }

                var dmaClocks = Maria.DoDMAProcessing();

                // CHEAT: Ace of Aces: Title screen has a single scanline flicker without this. Maria DMA clock counting probably not 100% accurate.
                if (i == 203 && FrameBuffer.Scanlines == 262 /*NTSC*/ || i == 228 && FrameBuffer.Scanlines == 312 /*PAL*/)
                {
                    if (dmaClocks == 152 && remainingRunClocks == 428 && (CPU.RunClocks == -4 || CPU.RunClocks == -8))
                    {
                        dmaClocks -= 4;
                    }
                }

                // Unsure exactly what to do if Maria DMA processing extends past the current scanline.
                // For now, throw away half remaining until we are within the current scanline.
                // KLAX initialization starts DMA without initializing the DLL data structure.
                // Maria processing then runs away causing an invalid CPU opcode to be executed that jams the machine.
                // So Maria must give up at some point, but not clear exactly how.
                // Anyway, this makes KLAX work without causing breakage elsewhere.
                while ((CPU.RunClocks + remainingRunClocks) < dmaClocks)
                {
                    dmaClocks >>= 1;
                }

                // Assume the CPU waits until the next div4 boundary to proceed after DMA processing.
                if ((dmaClocks & 3) != 0)
                {
                    dmaClocks += 4;
                    dmaClocks -= (dmaClocks & 3);
                }

                CPU.Clock     += (ulong)(dmaClocks / CPU.RunClocksMultiple);
                CPU.RunClocks -= dmaClocks;

                CPU.RunClocks += remainingRunClocks;

                CPU.Execute();
                if (CPU.Jammed)
                {
                    break;
                }
                if (CPU.EmulatorPreemptRequest)
                {
                    var remainingCpuClocks = 114 - (CPU.Clock - startOfScanlineCpuClock);
                    CPU.Clock    += remainingCpuClocks;
                    CPU.RunClocks = 0;
                }
            }
            Cart.EndFrame();
            Maria.EndFrame();
        }