From b0d09b7fb756f8d2018955b27a3699962b725595 Mon Sep 17 00:00:00 2001 From: Sean Fausett Date: Sat, 8 Jan 2011 00:55:17 +1300 Subject: [PATCH] Added touch input support to XNA build. Tweaked keyboard services, including how game port generates keys. --- Library/Xna/GameBase.cs | 13 -- .../Xna/Jellyfish.Library.Xna.Phone.csproj | 4 + Library/Xna/Jellyfish.Library.Xna.Xbox.csproj | 4 + Library/Xna/Jellyfish.Library.Xna.csproj | 4 + Library/Xna/TouchButton.cs | 12 ++ Library/Xna/TouchJoystick.cs | 49 ++++++ Library/Xna/TouchRegion.cs | 20 +++ Library/Xna/TouchRegionCollection.cs | 79 +++++++++ Virtu/CustomDictionary.xml | 1 + Virtu/GamePort.cs | 162 ++++++++++++++++-- Virtu/Keyboard.cs | 99 +---------- Virtu/Memory.cs | 34 ++-- Virtu/Services/GamePortService.cs | 111 +++++++++++- .../Services/SilverlightKeyboardService.cs | 8 +- Virtu/Wpf/Services/WpfKeyboardService.cs | 3 +- Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj | 3 + Virtu/Xna/Jellyfish.Virtu.Xna.csproj | 3 + Virtu/Xna/MainGame.cs | 19 +- Virtu/Xna/Services/XnaGamePortService.cs | 102 +++++++++-- Virtu/Xna/Services/XnaKeyboardService.cs | 18 +- 20 files changed, 575 insertions(+), 173 deletions(-) create mode 100644 Library/Xna/TouchButton.cs create mode 100644 Library/Xna/TouchJoystick.cs create mode 100644 Library/Xna/TouchRegion.cs create mode 100644 Library/Xna/TouchRegionCollection.cs diff --git a/Library/Xna/GameBase.cs b/Library/Xna/GameBase.cs index c33147e..227d325 100644 --- a/Library/Xna/GameBase.cs +++ b/Library/Xna/GameBase.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.GamerServices; @@ -37,18 +36,6 @@ public GameBase(string name) } } - [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")] - protected override void Update(GameTime gameTime) - { - var gamePadState = GamePad.GetState(PlayerIndex.One); - if (gamePadState.Buttons.Back == ButtonState.Pressed) - { - Exit(); - } - - base.Update(gameTime); - } - public string Name { get; private set; } public GraphicsDeviceManager GraphicsDeviceManager { get; private set; } public IGraphicsDeviceService GraphicsDeviceService { get; private set; } diff --git a/Library/Xna/Jellyfish.Library.Xna.Phone.csproj b/Library/Xna/Jellyfish.Library.Xna.Phone.csproj index c577a79..d2deec5 100644 --- a/Library/Xna/Jellyfish.Library.Xna.Phone.csproj +++ b/Library/Xna/Jellyfish.Library.Xna.Phone.csproj @@ -112,6 +112,10 @@ + + + + diff --git a/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj b/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj index 7e899d9..5b02fea 100644 --- a/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj +++ b/Library/Xna/Jellyfish.Library.Xna.Xbox.csproj @@ -127,6 +127,10 @@ + + + + diff --git a/Library/Xna/Jellyfish.Library.Xna.csproj b/Library/Xna/Jellyfish.Library.Xna.csproj index 692ba95..65eee2c 100644 --- a/Library/Xna/Jellyfish.Library.Xna.csproj +++ b/Library/Xna/Jellyfish.Library.Xna.csproj @@ -142,6 +142,10 @@ + + + + diff --git a/Library/Xna/TouchButton.cs b/Library/Xna/TouchButton.cs new file mode 100644 index 0000000..7930a63 --- /dev/null +++ b/Library/Xna/TouchButton.cs @@ -0,0 +1,12 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input.Touch; + +namespace Jellyfish.Library +{ + public sealed class TouchButton : TouchRegion + { + public bool HasValue { get { return Touch.HasValue; } } + public bool IsButtonDown { get { var touch = Touch.Value; return ((touch.State == TouchLocationState.Pressed) || (touch.State == TouchLocationState.Moved)); } } + public Vector2 Position { get { return Touch.Value.Position; } } + } +} diff --git a/Library/Xna/TouchJoystick.cs b/Library/Xna/TouchJoystick.cs new file mode 100644 index 0000000..044e44f --- /dev/null +++ b/Library/Xna/TouchJoystick.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input.Touch; + +namespace Jellyfish.Library +{ + public sealed class TouchJoystick : TouchRegion + { + public Vector2 GetJoystick() + { + TouchLocation touch; + bool isValid; + if (KeepLast && LastTouch.HasValue) + { + touch = LastTouch.Value; + isValid = (touch.State != TouchLocationState.Invalid); + } + else + { + touch = Touch.Value; + isValid = (touch.State == TouchLocationState.Pressed) || (touch.State == TouchLocationState.Moved); + } + if (isValid) + { + var center = Center; + var joystick = new Vector2((touch.Position.X - center.X) / Radius, (center.Y - touch.Position.Y) / Radius); + if (joystick.LengthSquared() > 1) + { + joystick.Normalize(); + } + return joystick; + } + + return Vector2.Zero; + } + + public void SetRadius(float radius) // scaled + { + Radius = (int)(radius * Math.Min(TouchPanel.DisplayWidth, TouchPanel.DisplayHeight)); + } + + public int Radius { get; set; } + public bool KeepLast { get; set; } + + public Vector2 Center { get { return FirstTouch.Value.Position; } } + public bool HasValue { get { return ((KeepLast && LastTouch.HasValue) || Touch.HasValue); } } + public Vector2 Position { get { return (KeepLast && LastTouch.HasValue) ? LastTouch.Value.Position : Touch.Value.Position; } } + } +} diff --git a/Library/Xna/TouchRegion.cs b/Library/Xna/TouchRegion.cs new file mode 100644 index 0000000..ef0b2bf --- /dev/null +++ b/Library/Xna/TouchRegion.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input.Touch; + +namespace Jellyfish.Library +{ + public class TouchRegion + { + public void SetBounds(float x, float y, float width, float height) // scaled + { + Bounds = new Rectangle((int)(x * TouchPanel.DisplayWidth), (int)(y * TouchPanel.DisplayHeight), (int)(width * TouchPanel.DisplayWidth), (int)(height * TouchPanel.DisplayHeight)); + } + + public Rectangle Bounds { get; set; } + public int Order { get; set; } + + internal TouchLocation? Touch { get; set; } + internal TouchLocation? FirstTouch { get; set; } + internal TouchLocation? LastTouch { get; set; } + } +} diff --git a/Library/Xna/TouchRegionCollection.cs b/Library/Xna/TouchRegionCollection.cs new file mode 100644 index 0000000..8d9c281 --- /dev/null +++ b/Library/Xna/TouchRegionCollection.cs @@ -0,0 +1,79 @@ +using System.Collections.ObjectModel; +using Microsoft.Xna.Framework.Input.Touch; + +namespace Jellyfish.Library +{ + public sealed class TouchRegionCollection : Collection + { + public TouchRegionCollection() + { + } + + public void Update(ref TouchCollection touches) + { + for (int i = 0; i < base.Count; i++) + { + base[i].Touch = null; + } + + for (int i = 0; i < touches.Count; i++) + { + var touch = touches[i]; + if (UpdateById(ref touch)) + { + continue; + } + + TouchLocation prevTouch; + if (touch.TryGetPreviousLocation(out prevTouch)) + { + UpdateByPosition(ref prevTouch); + } + else + { + UpdateByPosition(ref touch); + } + } + } + + private bool UpdateById(ref TouchLocation touch) + { + for (int i = 0; i < base.Count; i++) + { + var region = base[i]; + if (region.LastTouch.HasValue && (region.LastTouch.Value.Id == touch.Id)) + { + region.Touch = touch; + region.LastTouch = touch; + return true; + } + } + + return false; + } + + private void UpdateByPosition(ref TouchLocation touch) + { + if ((touch.State == TouchLocationState.Pressed) || (touch.State == TouchLocationState.Moved)) + { + TouchRegion topMostRegion = null; + + for (int i = 0; i < base.Count; i++) + { + var region = base[i]; + if (region.Bounds.Contains((int)touch.Position.X, (int)touch.Position.Y) && ((topMostRegion == null) || (topMostRegion.Order < region.Order))) + { + topMostRegion = region; + } + } + + if ((topMostRegion != null) && !topMostRegion.Touch.HasValue) + { + topMostRegion.Touch = touch; + topMostRegion.FirstTouch = touch; + topMostRegion.LastTouch = touch; + } + } + } + } +} diff --git a/Virtu/CustomDictionary.xml b/Virtu/CustomDictionary.xml index eba5ec1..c3f0bfb 100644 --- a/Virtu/CustomDictionary.xml +++ b/Virtu/CustomDictionary.xml @@ -18,6 +18,7 @@ DownRight + GamePad UpRight diff --git a/Virtu/GamePort.cs b/Virtu/GamePort.cs index 830483b..1787a4c 100644 --- a/Virtu/GamePort.cs +++ b/Virtu/GamePort.cs @@ -23,6 +23,30 @@ public override void Initialize() _gamePortService = Machine.Services.GetService(); JoystickDeadZone = 0.4f; +#if WINDOWS_PHONE + UseTouch = true; +#endif + InvertPaddles = true; // Raster Blaster + SwapPaddles = true; + Joystick0TouchX = 0.35f; + Joystick0TouchY = 0.6f; + Joystick0TouchWidth = 0.25f; + Joystick0TouchHeight = 0.4f; + Joystick0TouchRadius = 0.2f; + Joystick0TouchKeepLast = true; + Button0TouchX = 0; + Button0TouchY = 0; + Button0TouchWidth = 0.5f; + Button0TouchHeight = 1; + Button1TouchX = 0.5f; + Button1TouchY = 0; + Button1TouchWidth = 0.5f; + Button1TouchHeight = 1; + Button2TouchX = 0.75f; + Button2TouchY = 0; + Button2TouchWidth = 0.25f; + Button2TouchHeight = 0.25f; + Button2TouchOrder = 1; } public override void LoadState(BinaryReader reader, Version version) @@ -32,8 +56,10 @@ public override void LoadState(BinaryReader reader, Version version) throw new ArgumentNullException("reader"); } - JoystickDeadZone = reader.ReadSingle(); + InvertPaddles = reader.ReadBoolean(); + SwapPaddles = reader.ReadBoolean(); UseShiftKeyMod = reader.ReadBoolean(); + JoystickDeadZone = reader.ReadSingle(); UseKeyboard = reader.ReadBoolean(); Joystick0UpLeftKey = reader.ReadInt32(); @@ -55,6 +81,37 @@ public override void LoadState(BinaryReader reader, Version version) Button0Key = reader.ReadInt32(); Button1Key = reader.ReadInt32(); Button2Key = reader.ReadInt32(); + + UseTouch = reader.ReadBoolean(); + Joystick0TouchX = reader.ReadSingle(); + Joystick0TouchY = reader.ReadSingle(); + Joystick0TouchWidth = reader.ReadSingle(); + Joystick0TouchHeight = reader.ReadSingle(); + Joystick0TouchOrder = reader.ReadInt32(); + Joystick0TouchRadius = reader.ReadSingle(); + Joystick0TouchKeepLast = reader.ReadBoolean(); + Joystick1TouchX = reader.ReadSingle(); + Joystick1TouchY = reader.ReadSingle(); + Joystick1TouchWidth = reader.ReadSingle(); + Joystick1TouchHeight = reader.ReadSingle(); + Joystick1TouchOrder = reader.ReadInt32(); + Joystick1TouchRadius = reader.ReadSingle(); + Joystick1TouchKeepLast = reader.ReadBoolean(); + Button0TouchX = reader.ReadSingle(); + Button0TouchY = reader.ReadSingle(); + Button0TouchWidth = reader.ReadSingle(); + Button0TouchHeight = reader.ReadSingle(); + Button0TouchOrder = reader.ReadInt32(); + Button1TouchX = reader.ReadSingle(); + Button1TouchY = reader.ReadSingle(); + Button1TouchWidth = reader.ReadSingle(); + Button1TouchHeight = reader.ReadSingle(); + Button1TouchOrder = reader.ReadInt32(); + Button2TouchX = reader.ReadSingle(); + Button2TouchY = reader.ReadSingle(); + Button2TouchWidth = reader.ReadSingle(); + Button2TouchHeight = reader.ReadSingle(); + Button2TouchOrder = reader.ReadInt32(); } public override void SaveState(BinaryWriter writer) @@ -64,8 +121,10 @@ public override void SaveState(BinaryWriter writer) throw new ArgumentNullException("writer"); } - writer.Write(JoystickDeadZone); + writer.Write(InvertPaddles); + writer.Write(SwapPaddles); writer.Write(UseShiftKeyMod); + writer.Write(JoystickDeadZone); writer.Write(UseKeyboard); writer.Write(Joystick0UpLeftKey); @@ -87,6 +146,37 @@ public override void SaveState(BinaryWriter writer) writer.Write(Button0Key); writer.Write(Button1Key); writer.Write(Button2Key); + + writer.Write(UseTouch); + writer.Write(Joystick0TouchX); + writer.Write(Joystick0TouchY); + writer.Write(Joystick0TouchWidth); + writer.Write(Joystick0TouchHeight); + writer.Write(Joystick0TouchOrder); + writer.Write(Joystick0TouchRadius); + writer.Write(Joystick0TouchKeepLast); + writer.Write(Joystick1TouchX); + writer.Write(Joystick1TouchY); + writer.Write(Joystick1TouchWidth); + writer.Write(Joystick1TouchHeight); + writer.Write(Joystick1TouchOrder); + writer.Write(Joystick1TouchRadius); + writer.Write(Joystick1TouchKeepLast); + writer.Write(Button0TouchX); + writer.Write(Button0TouchY); + writer.Write(Button0TouchWidth); + writer.Write(Button0TouchHeight); + writer.Write(Button0TouchOrder); + writer.Write(Button1TouchX); + writer.Write(Button1TouchY); + writer.Write(Button1TouchWidth); + writer.Write(Button1TouchHeight); + writer.Write(Button1TouchOrder); + writer.Write(Button2TouchX); + writer.Write(Button2TouchY); + writer.Write(Button2TouchWidth); + writer.Write(Button2TouchHeight); + writer.Write(Button2TouchOrder); } public bool ReadButton0() @@ -121,61 +211,68 @@ public void TriggerTimers() ((Joystick0LeftKey > 0) && _keyboardService.IsKeyDown(Joystick0LeftKey)) || ((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey))) { - paddle0 -= 128; + paddle0 -= PaddleScale; } if (((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey)) || ((Joystick0RightKey > 0) && _keyboardService.IsKeyDown(Joystick0RightKey)) || ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) { - paddle0 += 128; + paddle0 += PaddleScale; } if (((Joystick0UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0UpLeftKey)) || ((Joystick0UpKey > 0) && _keyboardService.IsKeyDown(Joystick0UpKey)) || ((Joystick0UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick0UpRightKey))) { - paddle1 -= 128; + paddle1 -= PaddleScale; } if (((Joystick0DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick0DownLeftKey)) || ((Joystick0DownKey > 0) && _keyboardService.IsKeyDown(Joystick0DownKey)) || ((Joystick0DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick0DownRightKey))) { - paddle1 += 128; + paddle1 += PaddleScale; } if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || ((Joystick1LeftKey > 0) && _keyboardService.IsKeyDown(Joystick1LeftKey)) || ((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey))) { - paddle2 -= 128; + paddle2 -= PaddleScale; } if (((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey)) || ((Joystick1RightKey > 0) && _keyboardService.IsKeyDown(Joystick1RightKey)) || ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) { - paddle2 += 128; + paddle2 += PaddleScale; } if (((Joystick1UpLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1UpLeftKey)) || ((Joystick1UpKey > 0) && _keyboardService.IsKeyDown(Joystick1UpKey)) || ((Joystick1UpRightKey > 0) && _keyboardService.IsKeyDown(Joystick1UpRightKey))) { - paddle3 -= 128; + paddle3 -= PaddleScale; } if (((Joystick1DownLeftKey > 0) && _keyboardService.IsKeyDown(Joystick1DownLeftKey)) || ((Joystick1DownKey > 0) && _keyboardService.IsKeyDown(Joystick1DownKey)) || ((Joystick1DownRightKey > 0) && _keyboardService.IsKeyDown(Joystick1DownRightKey))) { - paddle3 += 128; + paddle3 += PaddleScale; } } + if (InvertPaddles) + { + paddle0 = 2 * PaddleScale - paddle0; + paddle1 = 2 * PaddleScale - paddle1; + paddle2 = 2 * PaddleScale - paddle2; + paddle3 = 2 * PaddleScale - paddle3; + } Paddle0Strobe = true; Paddle1Strobe = true; Paddle2Strobe = true; Paddle3Strobe = true; - Machine.Events.AddEvent(MathHelpers.ClampByte(paddle0) * CyclesPerValue, _resetPaddle0StrobeEvent); // [7-29] - Machine.Events.AddEvent(MathHelpers.ClampByte(paddle1) * CyclesPerValue, _resetPaddle1StrobeEvent); - Machine.Events.AddEvent(MathHelpers.ClampByte(paddle2) * CyclesPerValue, _resetPaddle2StrobeEvent); - Machine.Events.AddEvent(MathHelpers.ClampByte(paddle3) * CyclesPerValue, _resetPaddle3StrobeEvent); + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle1 : paddle0) * CyclesPerValue, _resetPaddle0StrobeEvent); // [7-29] + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle0 : paddle1) * CyclesPerValue, _resetPaddle1StrobeEvent); + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle3 : paddle2) * CyclesPerValue, _resetPaddle2StrobeEvent); + Machine.Events.AddEvent(MathHelpers.ClampByte(SwapPaddles ? paddle2 : paddle3) * CyclesPerValue, _resetPaddle3StrobeEvent); } private void ResetPaddle0StrobeEvent() @@ -198,8 +295,12 @@ private void ResetPaddle3StrobeEvent() Paddle3Strobe = false; } - public float JoystickDeadZone { get; set; } + public const int PaddleScale = 128; + + public bool InvertPaddles { get; set; } + public bool SwapPaddles { get; set; } public bool UseShiftKeyMod { get; set; } + public float JoystickDeadZone { get; set; } public bool UseKeyboard { get; set; } public int Joystick0UpLeftKey { get; set; } @@ -222,6 +323,37 @@ private void ResetPaddle3StrobeEvent() public int Button1Key { get; set; } public int Button2Key { get; set; } + public bool UseTouch { get; set; } + public float Joystick0TouchX { get; set; } + public float Joystick0TouchY { get; set; } + public float Joystick0TouchWidth { get; set; } + public float Joystick0TouchHeight { get; set; } + public int Joystick0TouchOrder { get; set; } + public float Joystick0TouchRadius { get; set; } + public bool Joystick0TouchKeepLast { get; set; } + public float Joystick1TouchX { get; set; } + public float Joystick1TouchY { get; set; } + public float Joystick1TouchWidth { get; set; } + public float Joystick1TouchHeight { get; set; } + public int Joystick1TouchOrder { get; set; } + public float Joystick1TouchRadius { get; set; } + public bool Joystick1TouchKeepLast { get; set; } + public float Button0TouchX { get; set; } + public float Button0TouchY { get; set; } + public float Button0TouchWidth { get; set; } + public float Button0TouchHeight { get; set; } + public int Button0TouchOrder { get; set; } + public float Button1TouchX { get; set; } + public float Button1TouchY { get; set; } + public float Button1TouchWidth { get; set; } + public float Button1TouchHeight { get; set; } + public int Button1TouchOrder { get; set; } + public float Button2TouchX { get; set; } + public float Button2TouchY { get; set; } + public float Button2TouchWidth { get; set; } + public float Button2TouchHeight { get; set; } + public int Button2TouchOrder { get; set; } + public bool Paddle0Strobe { get; private set; } public bool Paddle1Strobe { get; private set; } public bool Paddle2Strobe { get; private set; } diff --git a/Virtu/Keyboard.cs b/Virtu/Keyboard.cs index a839f32..db8f0ac 100644 --- a/Virtu/Keyboard.cs +++ b/Virtu/Keyboard.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using System.IO; using Jellyfish.Virtu.Services; @@ -15,7 +14,9 @@ public Keyboard(Machine machine) : public override void Initialize() { _keyboardService = Machine.Services.GetService(); - _gamePortService = Machine.Services.GetService(); + + UseGamePort = true; // Raster Blaster + Button2Key = ' '; } public override void LoadState(BinaryReader reader, Version version) @@ -76,99 +77,6 @@ public override void SaveState(BinaryWriter writer) writer.Write(Button2Key); } - [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - public int ReadLatch() - { - if (Strobe) - { - return Latch; - } - - if (UseGamePort) - { - if ((Joystick0UpLeftKey > 0) && _gamePortService.IsJoystick0Up && _gamePortService.IsJoystick0Left) - { - Latch = Joystick0UpLeftKey; - } - else if ((Joystick0UpRightKey > 0) && _gamePortService.IsJoystick0Up && _gamePortService.IsJoystick0Right) - { - Latch = Joystick0UpRightKey; - } - else if ((Joystick0DownLeftKey > 0) && _gamePortService.IsJoystick0Down && _gamePortService.IsJoystick0Left) - { - Latch = Joystick0DownLeftKey; - } - else if ((Joystick0DownRightKey > 0) && _gamePortService.IsJoystick0Down && _gamePortService.IsJoystick0Right) - { - Latch = Joystick0DownRightKey; - } - else if ((Joystick0UpKey > 0) && _gamePortService.IsJoystick0Up) - { - Latch = Joystick0UpKey; - } - else if ((Joystick0LeftKey > 0) && _gamePortService.IsJoystick0Left) - { - Latch = Joystick0LeftKey; - } - else if ((Joystick0RightKey > 0) && _gamePortService.IsJoystick0Right) - { - Latch = Joystick0RightKey; - } - else if ((Joystick0DownKey > 0) && _gamePortService.IsJoystick0Down) - { - Latch = Joystick0DownKey; - } - - if ((Joystick1UpLeftKey > 0) && _gamePortService.IsJoystick1Up && _gamePortService.IsJoystick1Left) // override - { - Latch = Joystick1UpLeftKey; - } - else if ((Joystick1UpRightKey > 0) && _gamePortService.IsJoystick1Up && _gamePortService.IsJoystick1Right) - { - Latch = Joystick1UpRightKey; - } - else if ((Joystick1DownLeftKey > 0) && _gamePortService.IsJoystick1Down && _gamePortService.IsJoystick1Left) - { - Latch = Joystick1DownLeftKey; - } - else if ((Joystick1DownRightKey > 0) && _gamePortService.IsJoystick1Down && _gamePortService.IsJoystick1Right) - { - Latch = Joystick1DownRightKey; - } - else if ((Joystick1UpKey > 0) && _gamePortService.IsJoystick1Up) - { - Latch = Joystick1UpKey; - } - else if ((Joystick1LeftKey > 0) && _gamePortService.IsJoystick1Left) - { - Latch = Joystick1LeftKey; - } - else if ((Joystick1RightKey > 0) && _gamePortService.IsJoystick1Right) - { - Latch = Joystick1RightKey; - } - else if ((Joystick1DownKey > 0) && _gamePortService.IsJoystick1Down) - { - Latch = Joystick1DownKey; - } - - if ((Button0Key > 0) && _gamePortService.IsButton0Down) // override - { - Latch = Button0Key; - } - else if ((Button1Key > 0) && _gamePortService.IsButton1Down) - { - Latch = Button1Key; - } - else if ((Button2Key > 0) && _gamePortService.IsButton2Down) - { - Latch = Button2Key; - } - } - - return Latch; - } - public void ResetStrobe() { Strobe = false; @@ -200,7 +108,6 @@ public void ResetStrobe() public bool Strobe { get; private set; } private KeyboardService _keyboardService; - private GamePortService _gamePortService; private int _latch; } diff --git a/Virtu/Memory.cs b/Virtu/Memory.cs index 3e675cb..19d37e6 100644 --- a/Virtu/Memory.cs +++ b/Virtu/Memory.cs @@ -233,56 +233,56 @@ private int ReadIoRegionC0C0(int address) { case 0xC000: case 0xC001: case 0xC002: case 0xC003: case 0xC004: case 0xC005: case 0xC006: case 0xC007: // [7-15] case 0xC008: case 0xC009: case 0xC00A: case 0xC00B: case 0xC00C: case 0xC00D: case 0xC00E: case 0xC00F: - return SetBit7(_keyboard.ReadLatch(), _keyboard.Strobe); + return SetBit7(_keyboard.Latch, _keyboard.Strobe); case 0xC010: _keyboard.ResetStrobe(); - return SetBit7(_keyboard.ReadLatch(), _keyboard.IsAnyKeyDown); + return SetBit7(_keyboard.Latch, _keyboard.IsAnyKeyDown); case 0xC011: - return SetBit7(_keyboard.ReadLatch(), !IsHighRamBank1); // Bank1' [5-22] + return SetBit7(_keyboard.Latch, !IsHighRamBank1); // Bank1' [5-22] case 0xC012: - return SetBit7(_keyboard.ReadLatch(), IsHighRamRead); + return SetBit7(_keyboard.Latch, IsHighRamRead); case 0xC013: - return SetBit7(_keyboard.ReadLatch(), IsRamReadAux); + return SetBit7(_keyboard.Latch, IsRamReadAux); case 0xC014: - return SetBit7(_keyboard.ReadLatch(), IsRamWriteAux); + return SetBit7(_keyboard.Latch, IsRamWriteAux); case 0xC015: - return SetBit7(_keyboard.ReadLatch(), IsRomC1CFInternal); + return SetBit7(_keyboard.Latch, IsRomC1CFInternal); case 0xC016: - return SetBit7(_keyboard.ReadLatch(), IsZeroPageAux); + return SetBit7(_keyboard.Latch, IsZeroPageAux); case 0xC017: - return SetBit7(_keyboard.ReadLatch(), IsRomC3C3External); + return SetBit7(_keyboard.Latch, IsRomC3C3External); case 0xC018: - return SetBit7(_keyboard.ReadLatch(), Is80Store); + return SetBit7(_keyboard.Latch, Is80Store); case 0xC019: - return SetBit7(_keyboard.ReadLatch(), !_video.IsVBlank); // Vbl' [7-5] + return SetBit7(_keyboard.Latch, !_video.IsVBlank); // Vbl' [7-5] case 0xC01A: - return SetBit7(_keyboard.ReadLatch(), IsText); + return SetBit7(_keyboard.Latch, IsText); case 0xC01B: - return SetBit7(_keyboard.ReadLatch(), IsMixed); + return SetBit7(_keyboard.Latch, IsMixed); case 0xC01C: - return SetBit7(_keyboard.ReadLatch(), IsPage2); + return SetBit7(_keyboard.Latch, IsPage2); case 0xC01D: - return SetBit7(_keyboard.ReadLatch(), IsHires); + return SetBit7(_keyboard.Latch, IsHires); case 0xC01E: - return SetBit7(_keyboard.ReadLatch(), IsCharSetAlternate); + return SetBit7(_keyboard.Latch, IsCharSetAlternate); case 0xC01F: - return SetBit7(_keyboard.ReadLatch(), Is80Columns); + return SetBit7(_keyboard.Latch, Is80Columns); case 0xC020: case 0xC021: case 0xC022: case 0xC023: case 0xC024: case 0xC025: case 0xC026: case 0xC027: // [7-8] case 0xC028: case 0xC029: case 0xC02A: case 0xC02B: case 0xC02C: case 0xC02D: case 0xC02E: case 0xC02F: diff --git a/Virtu/Services/GamePortService.cs b/Virtu/Services/GamePortService.cs index c5f5674..abe2c4c 100644 --- a/Virtu/Services/GamePortService.cs +++ b/Virtu/Services/GamePortService.cs @@ -1,4 +1,6 @@ -namespace Jellyfish.Virtu.Services +using System; + +namespace Jellyfish.Virtu.Services { public class GamePortService : MachineService { @@ -8,7 +10,65 @@ public GamePortService(Machine machine) : Paddle0 = Paddle1 = Paddle2 = Paddle3 = 255; // not connected } - public virtual void Update() { } // main thread + public virtual void Update() // main thread + { + var keyboard = Machine.Keyboard; + + if (keyboard.UseGamePort) + { + UpdateKey(keyboard.Joystick0UpKey, IsJoystick0Up, ref _isJoystick0UpKeyDown, ref _wasJoystick0UpKeyDown); + UpdateKey(keyboard.Joystick0LeftKey, IsJoystick0Left, ref _isJoystick0LeftKeyDown, ref _wasJoystick0LeftKeyDown); + UpdateKey(keyboard.Joystick0RightKey, IsJoystick0Right, ref _isJoystick0RightKeyDown, ref _wasJoystick0RightKeyDown); + UpdateKey(keyboard.Joystick0DownKey, IsJoystick0Down, ref _isJoystick0DownKeyDown, ref _wasJoystick0DownKeyDown); + UpdateKey(keyboard.Joystick0UpLeftKey, IsJoystick0Up && IsJoystick0Left, ref _isJoystick0UpLeftKeyDown, ref _wasJoystick0UpLeftKeyDown); + UpdateKey(keyboard.Joystick0UpRightKey, IsJoystick0Up && IsJoystick0Right, ref _isJoystick0UpRightKeyDown, ref _wasJoystick0UpRightKeyDown); + UpdateKey(keyboard.Joystick0DownLeftKey, IsJoystick0Down && IsJoystick0Left, ref _isJoystick0DownLeftKeyDown, ref _wasJoystick0DownLeftKeyDown); + UpdateKey(keyboard.Joystick0DownRightKey, IsJoystick0Down && IsJoystick0Right, ref _isJoystick0DownRightKeyDown, ref _wasJoystick0DownRightKeyDown); + UpdateKey(keyboard.Joystick1UpKey, IsJoystick1Up, ref _isJoystick1UpKeyDown, ref _wasJoystick1UpKeyDown); + UpdateKey(keyboard.Joystick1LeftKey, IsJoystick1Left, ref _isJoystick1LeftKeyDown, ref _wasJoystick1LeftKeyDown); + UpdateKey(keyboard.Joystick1RightKey, IsJoystick1Right, ref _isJoystick1RightKeyDown, ref _wasJoystick1RightKeyDown); + UpdateKey(keyboard.Joystick1DownKey, IsJoystick1Down, ref _isJoystick1DownKeyDown, ref _wasJoystick1DownKeyDown); + UpdateKey(keyboard.Joystick1UpLeftKey, IsJoystick1Up && IsJoystick1Left, ref _isJoystick1UpLeftKeyDown, ref _wasJoystick1UpLeftKeyDown); + UpdateKey(keyboard.Joystick1UpRightKey, IsJoystick1Up && IsJoystick1Right, ref _isJoystick1UpRightKeyDown, ref _wasJoystick1UpRightKeyDown); + UpdateKey(keyboard.Joystick1DownLeftKey, IsJoystick1Down && IsJoystick1Left, ref _isJoystick1DownLeftKeyDown, ref _wasJoystick1DownLeftKeyDown); + UpdateKey(keyboard.Joystick1DownRightKey, IsJoystick1Down && IsJoystick1Right, ref _isJoystick1DownRightKeyDown, ref _wasJoystick1DownRightKeyDown); + UpdateKey(keyboard.Button0Key, IsButton0Down, ref _isButton0KeyDown, ref _wasButton0KeyDown); + UpdateKey(keyboard.Button1Key, IsButton1Down, ref _isButton1KeyDown, ref _wasButton1KeyDown); + UpdateKey(keyboard.Button2Key, IsButton2Down, ref _isButton2KeyDown, ref _wasButton2KeyDown); + + if (_lastKey > 0) // repeat last key + { + long time = DateTime.UtcNow.Ticks; + if (time - _lastTime >= _repeatTime) + { + _lastTime = time; + _repeatTime = RepeatSpeed; + keyboard.Latch = _lastKey; + } + } + } + } + + private void UpdateKey(int key, bool isActive, ref bool isKeyDown, ref bool wasKeyDown) + { + wasKeyDown = isKeyDown; + isKeyDown = (key > 0) && isActive; + + if (isKeyDown != wasKeyDown) + { + if (isKeyDown) + { + _lastKey = key; + _lastTime = DateTime.UtcNow.Ticks; + _repeatTime = RepeatDelay; + Machine.Keyboard.Latch = key; + } + else if (key == _lastKey) + { + _lastKey = 0; + } + } + } public int Paddle0 { get; protected set; } public int Paddle1 { get; protected set; } @@ -28,5 +88,52 @@ public virtual void Update() { } // main thread public bool IsButton0Down { get; protected set; } public bool IsButton1Down { get; protected set; } public bool IsButton2Down { get; protected set; } + + private static readonly long RepeatDelay = TimeSpan.FromMilliseconds(500).Ticks; + private static readonly long RepeatSpeed = TimeSpan.FromMilliseconds(32).Ticks; + + private bool _isJoystick0UpLeftKeyDown; + private bool _isJoystick0UpKeyDown; + private bool _isJoystick0UpRightKeyDown; + private bool _isJoystick0LeftKeyDown; + private bool _isJoystick0RightKeyDown; + private bool _isJoystick0DownLeftKeyDown; + private bool _isJoystick0DownKeyDown; + private bool _isJoystick0DownRightKeyDown; + private bool _isJoystick1UpLeftKeyDown; + private bool _isJoystick1UpKeyDown; + private bool _isJoystick1UpRightKeyDown; + private bool _isJoystick1LeftKeyDown; + private bool _isJoystick1RightKeyDown; + private bool _isJoystick1DownLeftKeyDown; + private bool _isJoystick1DownKeyDown; + private bool _isJoystick1DownRightKeyDown; + private bool _isButton0KeyDown; + private bool _isButton1KeyDown; + private bool _isButton2KeyDown; + + private bool _wasJoystick0UpLeftKeyDown; + private bool _wasJoystick0UpKeyDown; + private bool _wasJoystick0UpRightKeyDown; + private bool _wasJoystick0LeftKeyDown; + private bool _wasJoystick0RightKeyDown; + private bool _wasJoystick0DownLeftKeyDown; + private bool _wasJoystick0DownKeyDown; + private bool _wasJoystick0DownRightKeyDown; + private bool _wasJoystick1UpLeftKeyDown; + private bool _wasJoystick1UpKeyDown; + private bool _wasJoystick1UpRightKeyDown; + private bool _wasJoystick1LeftKeyDown; + private bool _wasJoystick1RightKeyDown; + private bool _wasJoystick1DownLeftKeyDown; + private bool _wasJoystick1DownKeyDown; + private bool _wasJoystick1DownRightKeyDown; + private bool _wasButton0KeyDown; + private bool _wasButton1KeyDown; + private bool _wasButton2KeyDown; + + private int _lastKey; + private long _lastTime; + private long _repeatTime; } } diff --git a/Virtu/Silverlight/Services/SilverlightKeyboardService.cs b/Virtu/Silverlight/Services/SilverlightKeyboardService.cs index b56f730..b7131e2 100644 --- a/Virtu/Silverlight/Services/SilverlightKeyboardService.cs +++ b/Virtu/Silverlight/Services/SilverlightKeyboardService.cs @@ -33,9 +33,9 @@ public override void Update() // main thread { _updateAnyKeyDown = false; IsAnyKeyDown = false; - foreach (Key key in KeyValues) + for (int i = 0; i < KeyValues.Length; i++) { - if (IsKeyDown(key)) + if (IsKeyDown(KeyValues[i])) { IsAnyKeyDown = true; break; @@ -111,9 +111,9 @@ private void OnPageKeyUp(object sender, KeyEventArgs e) private void OnPageLostFocus(object sender, RoutedEventArgs e) // reset keyboard state on lost focus; can't access keyboard state on got focus { IsAnyKeyDown = false; - foreach (Key key in KeyValues) + for (int i = 0; i < KeyValues.Length; i++) { - _states[(int)key] = false; + _states[(int)KeyValues[i]] = false; } } diff --git a/Virtu/Wpf/Services/WpfKeyboardService.cs b/Virtu/Wpf/Services/WpfKeyboardService.cs index c3e4e75..7d9cc82 100644 --- a/Virtu/Wpf/Services/WpfKeyboardService.cs +++ b/Virtu/Wpf/Services/WpfKeyboardService.cs @@ -33,8 +33,9 @@ public override void Update() // main thread { _updateAnyKeyDown = false; IsAnyKeyDown = false; - foreach (Key key in KeyValues) + for (int i = 0; i < KeyValues.Length; i++) { + var key = KeyValues[i]; bool isKeyDown = keyboard.IsKeyDown(key); _states[(int)key] = isKeyDown; if (isKeyDown) diff --git a/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj b/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj index 5d01606..c0e2971 100644 --- a/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj +++ b/Virtu/Xna/Jellyfish.Virtu.Xna.Xbox.csproj @@ -81,6 +81,9 @@ False + + False + False diff --git a/Virtu/Xna/Jellyfish.Virtu.Xna.csproj b/Virtu/Xna/Jellyfish.Virtu.Xna.csproj index 45a553a..1fdfad0 100644 --- a/Virtu/Xna/Jellyfish.Virtu.Xna.csproj +++ b/Virtu/Xna/Jellyfish.Virtu.Xna.csproj @@ -84,6 +84,9 @@ False + + False + False diff --git a/Virtu/Xna/MainGame.cs b/Virtu/Xna/MainGame.cs index db7ad38..bdf90b4 100644 --- a/Virtu/Xna/MainGame.cs +++ b/Virtu/Xna/MainGame.cs @@ -2,6 +2,8 @@ using Jellyfish.Virtu.Services; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; namespace Jellyfish.Virtu { @@ -60,8 +62,17 @@ protected override void BeginRun() protected override void Update(GameTime gameTime) { - _keyboardService.Update(); - _gamePortService.Update(); + var keyboardState = Microsoft.Xna.Framework.Input.Keyboard.GetState(); + var gamePadState = GamePad.GetState(PlayerIndex.One); + var touches = TouchPanel.GetState(); + + if (gamePadState.Buttons.Back == ButtonState.Pressed) + { + Exit(); + } + + _keyboardService.Update(ref keyboardState, ref gamePadState); + _gamePortService.Update(ref gamePadState, ref touches); base.Update(gameTime); } @@ -83,8 +94,8 @@ protected override void EndRun() private DebugService _debugService; private StorageService _storageService; - private KeyboardService _keyboardService; - private GamePortService _gamePortService; + private XnaKeyboardService _keyboardService; + private XnaGamePortService _gamePortService; private AudioService _audioService; private VideoService _videoService; } diff --git a/Virtu/Xna/Services/XnaGamePortService.cs b/Virtu/Xna/Services/XnaGamePortService.cs index 979521c..8e93682 100644 --- a/Virtu/Xna/Services/XnaGamePortService.cs +++ b/Virtu/Xna/Services/XnaGamePortService.cs @@ -1,5 +1,7 @@ -using Microsoft.Xna.Framework; +using System.Diagnostics.CodeAnalysis; +using Jellyfish.Library; using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Input.Touch; namespace Jellyfish.Virtu.Services { @@ -8,24 +10,28 @@ public sealed class XnaGamePortService : GamePortService public XnaGamePortService(Machine machine) : base(machine) { + _touchRegions = new TouchRegionCollection { _touchJoystick0, _touchJoystick1, _touchButton0, _touchButton1, _touchButton2 }; } - public override void Update() // main thread + [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] + public void Update(ref GamePadState gamePadState, ref TouchCollection touches) // main thread { _lastState = _state; - _state = GamePad.GetState(PlayerIndex.One); + _state = gamePadState; + + var gamePort = Machine.GamePort; if (_state.IsConnected && (_state != _lastState)) { var left = _state.ThumbSticks.Left; var right = _state.ThumbSticks.Right; var dpad = _state.DPad; - var gamePort = Machine.GamePort; + var buttons = _state.Buttons; - Paddle0 = (int)((1 + left.X) * PaddleScale); - Paddle1 = (int)((1 - left.Y) * PaddleScale); // invert y - Paddle2 = (int)((1 + right.X) * PaddleScale); - Paddle3 = (int)((1 - right.Y) * PaddleScale); // invert y + Paddle0 = (int)((1 + left.X) * GamePort.PaddleScale); + Paddle1 = (int)((1 - left.Y) * GamePort.PaddleScale); // invert y + Paddle2 = (int)((1 + right.X) * GamePort.PaddleScale); + Paddle3 = (int)((1 - right.Y) * GamePort.PaddleScale); // invert y IsJoystick0Up = ((left.Y > gamePort.JoystickDeadZone) || (dpad.Up == ButtonState.Pressed)); IsJoystick0Left = ((left.X < -gamePort.JoystickDeadZone) || (dpad.Left == ButtonState.Pressed)); @@ -37,15 +43,85 @@ public override void Update() // main thread IsJoystick1Right = (right.X > gamePort.JoystickDeadZone); IsJoystick1Down = (right.Y < -gamePort.JoystickDeadZone); - IsButton0Down = ((_state.Buttons.A == ButtonState.Pressed) || (_state.Buttons.LeftShoulder == ButtonState.Pressed)); - IsButton1Down = ((_state.Buttons.B == ButtonState.Pressed) || (_state.Buttons.RightShoulder == ButtonState.Pressed)); - IsButton2Down = (_state.Buttons.X == ButtonState.Pressed); + IsButton0Down = ((buttons.A == ButtonState.Pressed) || (buttons.LeftShoulder == ButtonState.Pressed)); + IsButton1Down = ((buttons.B == ButtonState.Pressed) || (buttons.RightShoulder == ButtonState.Pressed)); + IsButton2Down = (buttons.X == ButtonState.Pressed); + } + + if (gamePort.UseTouch) // override + { + UpdateTouch(ref touches); + } + + base.Update(); + } + + private void UpdateTouch(ref TouchCollection touches) + { + var gamePort = Machine.GamePort; + + _touchJoystick0.SetBounds(gamePort.Joystick0TouchX, gamePort.Joystick0TouchY, gamePort.Joystick0TouchWidth, gamePort.Joystick0TouchHeight); + _touchJoystick0.SetRadius(gamePort.Joystick0TouchRadius); + _touchJoystick0.KeepLast = gamePort.Joystick0TouchKeepLast; + _touchJoystick0.Order = gamePort.Joystick0TouchOrder; + _touchJoystick1.SetBounds(gamePort.Joystick1TouchX, gamePort.Joystick1TouchY, gamePort.Joystick1TouchWidth, gamePort.Joystick1TouchHeight); + _touchJoystick1.SetRadius(gamePort.Joystick1TouchRadius); + _touchJoystick1.KeepLast = gamePort.Joystick1TouchKeepLast; + _touchJoystick1.Order = gamePort.Joystick1TouchOrder; + _touchButton0.SetBounds(gamePort.Button0TouchX, gamePort.Button0TouchY, gamePort.Button0TouchWidth, gamePort.Button0TouchHeight); + _touchButton0.Order = gamePort.Button0TouchOrder; + _touchButton1.SetBounds(gamePort.Button1TouchX, gamePort.Button1TouchY, gamePort.Button1TouchWidth, gamePort.Button1TouchHeight); + _touchButton1.Order = gamePort.Button1TouchOrder; + _touchButton2.SetBounds(gamePort.Button2TouchX, gamePort.Button2TouchY, gamePort.Button2TouchWidth, gamePort.Button2TouchHeight); + _touchButton2.Order = gamePort.Button2TouchOrder; + + _touchRegions.Update(ref touches); + + if (_touchJoystick0.HasValue) + { + var joystick = _touchJoystick0.GetJoystick(); + + Paddle0 = (int)((1 + joystick.X) * GamePort.PaddleScale); + Paddle1 = (int)((1 - joystick.Y) * GamePort.PaddleScale); // invert y + + IsJoystick0Up = (joystick.Y > gamePort.JoystickDeadZone); + IsJoystick0Left = (joystick.X < -gamePort.JoystickDeadZone); + IsJoystick0Right = (joystick.X > gamePort.JoystickDeadZone); + IsJoystick0Down = (joystick.Y < -gamePort.JoystickDeadZone); + } + if (_touchJoystick1.HasValue) + { + var joystick = _touchJoystick1.GetJoystick(); + + Paddle2 = (int)((1 + joystick.X) * GamePort.PaddleScale); + Paddle3 = (int)((1 - joystick.Y) * GamePort.PaddleScale); // invert y + + IsJoystick1Up = (joystick.Y > gamePort.JoystickDeadZone); + IsJoystick1Left = (joystick.X < -gamePort.JoystickDeadZone); + IsJoystick1Right = (joystick.X > gamePort.JoystickDeadZone); + IsJoystick1Down = (joystick.Y < -gamePort.JoystickDeadZone); + } + if (_touchButton0.HasValue) + { + IsButton0Down = _touchButton0.IsButtonDown; + } + if (_touchButton1.HasValue) + { + IsButton1Down = _touchButton1.IsButtonDown; + } + if (_touchButton2.HasValue) + { + IsButton2Down = _touchButton2.IsButtonDown; } } - private const int PaddleScale = 128; - private GamePadState _state; private GamePadState _lastState; + private TouchJoystick _touchJoystick0 = new TouchJoystick(); + private TouchJoystick _touchJoystick1 = new TouchJoystick(); + private TouchButton _touchButton0 = new TouchButton(); + private TouchButton _touchButton1 = new TouchButton(); + private TouchButton _touchButton2 = new TouchButton(); + private TouchRegionCollection _touchRegions; } } diff --git a/Virtu/Xna/Services/XnaKeyboardService.cs b/Virtu/Xna/Services/XnaKeyboardService.cs index 2fda62d..2a2d43a 100644 --- a/Virtu/Xna/Services/XnaKeyboardService.cs +++ b/Virtu/Xna/Services/XnaKeyboardService.cs @@ -18,19 +18,21 @@ public override bool IsKeyDown(int key) return IsKeyDown((Keys)key); } - public override void Update() // main thread + [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")] + public void Update(ref KeyboardState keyboardState, ref GamePadState gamePadState) // main thread { _lastState = _state; - _state = Microsoft.Xna.Framework.Input.Keyboard.GetState(); + _state = keyboardState; - var gamePadState = GamePad.GetState(PlayerIndex.One); - bool gamePadControl = (gamePadState.Buttons.LeftStick == ButtonState.Pressed); + var gamePadButtons = gamePadState.Buttons; + bool gamePadControl = (gamePadButtons.LeftStick == ButtonState.Pressed); if (_state != _lastState) { IsAnyKeyDown = false; - foreach (Keys key in KeyValues) // xna doesn't support buffered input; loses input order and could lose keys between updates + for (int i = 0; i < KeyValues.Length; i++) // xna doesn't support buffered input; loses input order and could lose keys between updates { + var key = KeyValues[i]; if (_state.IsKeyDown(key)) { IsAnyKeyDown = true; @@ -70,9 +72,9 @@ public override void Update() // main thread IsControlKeyDown = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl); IsShiftKeyDown = IsKeyDown(Keys.LeftShift) || IsKeyDown(Keys.RightShift); - IsOpenAppleKeyDown = IsKeyDown(Keys.LeftAlt) || IsKeyDown(Keys.NumPad0) || (gamePadState.Buttons.LeftShoulder == ButtonState.Pressed); - IsCloseAppleKeyDown = IsKeyDown(Keys.RightAlt) || IsKeyDown(Keys.Decimal) || (gamePadState.Buttons.RightShoulder == ButtonState.Pressed); - IsResetKeyDown = (IsControlKeyDown && IsKeyDown(Keys.Back)) || (gamePadControl && (gamePadState.Buttons.Start == ButtonState.Pressed)); + IsOpenAppleKeyDown = IsKeyDown(Keys.LeftAlt) || IsKeyDown(Keys.NumPad0) || (gamePadButtons.LeftShoulder == ButtonState.Pressed); + IsCloseAppleKeyDown = IsKeyDown(Keys.RightAlt) || IsKeyDown(Keys.Decimal) || (gamePadButtons.RightShoulder == ButtonState.Pressed); + IsResetKeyDown = (IsControlKeyDown && IsKeyDown(Keys.Back)) || (gamePadControl && (gamePadButtons.Start == ButtonState.Pressed)); base.Update(); }