/// <summary> /// Call the from the IN instruction to play the sounds as per the original hardware's sound board /// </summary> /// <param name="machine"></param> internal static void PlaySounds(i8080 machine) { if (machine.PORT_OUT_3 != LastOutPort3) { if ((machine.PORT_OUT_3 & 0x1) != 0 && (LastOutPort3 & 0x1) == 0) { PlayLoopingSoundFile(Port3Sounds[0]); } else if ((machine.PORT_OUT_3 & 0x1) == 0 && (LastOutPort3 & 0x1) != 0) { StopLoopingSoundFile(); } else { PlaySound(machine.PORT_OUT_3, LastOutPort3, Port3Sounds, true); } LastOutPort3 = machine.PORT_OUT_3; } if (machine.PORT_OUT_5 != m_lastOutPort5) { PlaySound(machine.PORT_OUT_5, m_lastOutPort5, Port5Sounds, true); m_lastOutPort5 = machine.PORT_OUT_5; } }
/// <summary> /// Checks the controllers buttons, Inputs set by a controller will be cleared if they are no longer active /// </summary> /// <param name="machine"></param> /// <param name="state"></param> /// <param name="flag"></param> /// <param name="portByte"></param> private static void CheckXInputButtons(i8080 machine, State state, GamepadButtonFlags flag, byte portByte) { if ((state.Gamepad.Buttons & flag) != 0) { machine.PORT_IN_1 |= portByte; m_controllerState |= (ushort)flag; } else { if ((m_controllerState & (ushort)flag) != 0) { machine.PORT_IN_1 = unchecked ((byte)(machine.PORT_IN_1 & (byte)~portByte)); m_controllerState = unchecked ((ushort)(m_controllerState & (ushort)~flag)); } } }
/// <summary> /// Checks the controllers left stick, Inputs set by a controller will be cleared if they are no longer active /// </summary> /// <param name="machine"></param> /// <param name="state"></param> private static void CheckXInputSticks(i8080 machine, State state) { if (state.Gamepad.LeftThumbX > Gamepad.LeftThumbDeadZone) { machine.PORT_IN_1 |= 0x40; m_stickRight = true; } else if (state.Gamepad.LeftThumbX < -Gamepad.LeftThumbDeadZone) { machine.PORT_IN_1 |= 0x20; m_stickLeft = true; } else if (state.Gamepad.LeftThumbY < -Gamepad.LeftThumbDeadZone) { machine.PORT_IN_1 |= 0x08; m_stickDown = true; } else if (state.Gamepad.LeftThumbY > Gamepad.LeftThumbDeadZone) { machine.PORT_IN_1 |= 0x80; m_stickUp = true; } else { if (m_stickRight) { machine.PORT_IN_1 = unchecked ((byte)(machine.PORT_IN_1 & (byte)~0x40)); m_stickRight = false; } else if (m_stickLeft) { machine.PORT_IN_1 = unchecked ((byte)(machine.PORT_IN_1 & (byte)~0x20)); m_stickLeft = false; } else if (m_stickUp) { machine.PORT_IN_1 = unchecked ((byte)(machine.PORT_IN_1 & (byte)~0x80)); m_stickUp = false; } else if (m_stickDown) { machine.PORT_IN_1 = unchecked ((byte)(machine.PORT_IN_1 & (byte)~0x08)); m_stickDown = false; } } }
// This will send values to the Input port in response to controller actions public static void Check(i8080 machine) { State state; if (machine.controller.GetState(out state)) { CheckXInputButtons(machine, state, GamepadButtonFlags.Back, 0x01); CheckXInputButtons(machine, state, GamepadButtonFlags.Start, 0x04); CheckXInputButtons(machine, state, GamepadButtonFlags.A, 0x10); CheckXInputButtons(machine, state, GamepadButtonFlags.DPadLeft, 0x20); CheckXInputButtons(machine, state, GamepadButtonFlags.DPadRight, 0x40); CheckXInputButtons(machine, state, GamepadButtonFlags.DPadUp, 0x80); CheckXInputButtons(machine, state, GamepadButtonFlags.DPadDown, 0x08); CheckXInputSticks(machine, state); } }
private void LoadProgram(UInt16 startingAddress) { FileLoader load = new FileLoader(); load.AddFile("SpaceInvaders\\ROM\\invaders.h"); load.AddFile("SpaceInvaders\\ROM\\invaders.g"); load.AddFile("SpaceInvaders\\ROM\\invaders.f"); load.AddFile("SpaceInvaders\\ROM\\invaders.e"); _cpu = new i8080(); _cpu.LoadInstructions(load.LoadData(), startingAddress); ShiftOffsetDevice _soDevice = new ShiftOffsetDevice(); ShiftDevice _device = new ShiftDevice(_soDevice); // input device port 1: First Arcade Port _cpu.AddInputDevice(_port1, 1); // input device port 2: Second Arcade Port _cpu.AddInputDevice(_port2, 2); // input device port 3: shift register output to cpu _cpu.AddInputDevice(_device, 3); // output device port 2: shift offset _cpu.AddOutputDevice(_soDevice, 2); // output device port 3: add sound port _cpu.AddOutputDevice(_sound3, 3); // output device port 4: shift register input from cpu _cpu.AddOutputDevice(_device, 4); // output device port 5: add sound port _cpu.AddOutputDevice(_sound5, 5); }
/// <summary> /// Paint the screen to a device context /// </summary> /// <param name="graphics"></param> /// <param name="machine"></param> /// <param name="rectangle"></param> /// <param name="offset"></param> /// <param name="factor"></param> internal static void Paint(Graphics graphics, i8080 machine, Rectangle rectangle, int offset, int factor) { m_scaleFactor = factor; if (m_gameBitmap == null || m_lastScaleFactor != m_scaleFactor) { m_lastScaleFactor = m_scaleFactor; m_gameBitmap = new Bitmap(224 * m_scaleFactor, 256 * m_scaleFactor + offset / m_scaleFactor); m_graphics = Graphics.FromImage(m_gameBitmap); m_fpsCounter = new Stopwatch(); m_fpsCounter.Start(); for (int i = 0; i < Cache.Length; ++i) { Cache[i] = 0xff; } } machine.Painting = true; bool changed = Render(m_graphics, machine.RAM, offset / m_scaleFactor); if (changed) { machine.Frames++; } graphics.DrawImageUnscaled(m_gameBitmap, (rectangle.Width - m_gameBitmap.Width) / 2, rectangle.Top); graphics.DrawString("fps: " + m_fps.ToString("F"), DrawFont, Brushes.Green, 3.0f, rectangle.Height - 20); if (m_fpsCounter.ElapsedMilliseconds > 1000) { m_fps = (double)machine.Frames / m_fpsCounter.ElapsedMilliseconds * 1000.0; m_fps = Math.Round(m_fps * 2, MidpointRounding.AwayFromZero) / 2; m_fpsCounter.Restart(); machine.Frames = 0; } machine.Painting = false; }
/// <summary> /// /// </summary> /// <param name="machine"></param> public static void Run(i8080 machine) { Stopwatch sw = new Stopwatch(); sw.Start(); Stopwatch sw2 = new Stopwatch(); sw2.Start(); int ticks = (int)(1000.0 / 60.0 / 2.0) * 10000; bool top = true; int c = 0; long t = 0; double s1; double s2; double clockRate = 0; machine.MemoryProtection = true; while (machine.On) { if (c % 100 == 0) { s1 = (double)(machine.Cycles + 1); s2 = (double)(sw.ElapsedMilliseconds + 1); clockRate = s1 / s2; } if (clockRate < 2000) { machine.RunNext(); } if (t > ticks) { if (machine.Interupt((byte)(top ? 0xcf : 0xd7))) { top = !top; } sw2.Restart(); } if (c % 100 == 0) { t = sw2.ElapsedTicks; } //if (c % 250 == 0) //{ // Thread.Sleep(1); //} if (c % 25 == 0) { if (machine.controller != null) { if (machine.controller.IsConnected) { Input.Check(machine); } } } c++; } }