Cosmetic changes.

Modified to clear audio buffer on reset.
Refactored keyboard services and unified key bindings where practical.

--HG--
extra : convert_revision : svn%3Affd33b8c-2492-42e0-bdc5-587b920b7d6d/trunk%4044385
This commit is contained in:
Sean Fausett 2010-04-01 23:00:24 +00:00
parent 0d1a883260
commit 26bd5e3aa9
24 changed files with 233 additions and 284 deletions

View File

@ -6,6 +6,11 @@ namespace Jellyfish.Library
{
public class ApplicationBase : Application
{
public ApplicationBase() :
this(null)
{
}
public ApplicationBase(string name)
{
Name = name;
@ -17,6 +22,7 @@ namespace Jellyfish.Library
private void OnApplicationUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
MessageBox.Show(GetExceptionMessage(e.ExceptionObject), GetExceptionCaption("Application Exception", false), MessageBoxButton.OK);
e.Handled = true;
}
//private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
@ -48,8 +54,7 @@ namespace Jellyfish.Library
{
message.Append(exception.Message.ToString());
message.Append(Environment.NewLine);
message.Append(Environment.NewLine);
message.Append(exception.ToString()); // includes stack trace
message.Append(exception.StackTrace.ToString());
}
return message.ToString();

View File

@ -9,6 +9,12 @@ namespace Jellyfish.Library
{
public class ApplicationBase : Application
{
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public ApplicationBase() :
this(null)
{
}
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public ApplicationBase(string name)
{
@ -21,8 +27,8 @@ namespace Jellyfish.Library
private void OnApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(GetExceptionMessage(e.Exception), GetExceptionCaption("Application Dispatcher Exception", true));
Shutdown();
e.Handled = true;
Shutdown();
}
private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
@ -55,8 +61,7 @@ namespace Jellyfish.Library
{
message.Append(exception.Message.ToString());
message.Append(Environment.NewLine);
message.Append(Environment.NewLine);
message.Append(exception.ToString()); // includes stack trace
message.Append(exception.StackTrace.ToString());
}
return message.ToString();

View File

@ -7,6 +7,11 @@ namespace Jellyfish.Library
{
public class GameBase : Game
{
public GameBase() :
this(null)
{
}
public GameBase(string name)
{
Name = name;
@ -29,6 +34,7 @@ namespace Jellyfish.Library
{
Exit();
}
base.Update(gameTime);
}

View File

@ -63,7 +63,7 @@ namespace Jellyfish.Virtu
if (!Read3Nibbles(0xD5, 0xAA, 0x96, 0x304))
break; // no address prologue
int readVolume = ReadNibble44();
/*int readVolume = */ReadNibble44();
int readTrack = ReadNibble44();
if (readTrack != track)
@ -94,7 +94,7 @@ namespace Jellyfish.Virtu
}
if (sectorsDone != 0xFFFF)
throw new Exception("disk error"); // TODO: we should alert the user and "dump" a NIB
throw new InvalidOperationException("disk error"); // TODO: we should alert the user and "dump" a NIB
}
private byte ReadNibble()
@ -110,16 +110,15 @@ namespace Jellyfish.Virtu
private bool Read3Nibbles(byte data1, byte data2, byte data3, int maxReads)
{
bool result = false;
byte nibble;
while (--maxReads > 0)
{
if ((nibble = ReadNibble()) != data1)
if (ReadNibble() != data1)
continue;
if ((nibble = ReadNibble()) != data2)
if (ReadNibble() != data2)
continue;
if ((nibble = ReadNibble()) != data3)
if (ReadNibble() != data3)
continue;
result = true;

View File

@ -18,7 +18,6 @@ namespace Jellyfish.Virtu
_gamePortService = Machine.Services.GetService<GamePortService>();
_keyboardService.AsciiKeyDown += (sender, e) => Latch = e.AsciiKey;
Machine.Video.VSync += OnVideoVSync;
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
@ -121,30 +120,6 @@ namespace Jellyfish.Virtu
Strobe = false;
}
private void OnVideoVSync(object sender, EventArgs e)
{
if (_keyboardService.IsResetKeyDown)
{
Machine.Reset();
_keyboardService.WaitForResetKeyUp();
}
else if (_keyboardService.IsCpuThrottleKeyDown)
{
Machine.Cpu.ToggleThrottle();
_keyboardService.WaitForKeyUp();
}
else if (_keyboardService.IsVideoFullScreenKeyDown)
{
Machine.Video.ToggleFullScreen();
_keyboardService.WaitForKeyUp();
}
else if (_keyboardService.IsVideoMonochromeKeyDown)
{
Machine.Video.ToggleMonochrome();
_keyboardService.WaitForKeyUp();
}
}
public bool IsAnyKeyDown { get { return _keyboardService.IsAnyKeyDown; } }
public bool Strobe { get; private set; }

View File

@ -38,7 +38,7 @@ namespace Jellyfish.Virtu
public void Reset()
{
Components.ForEach(component => component.Reset());
Components.ForEach(component => component.Reset()); // while machine starting or paused
}
public void Start()

View File

@ -24,6 +24,11 @@ namespace Jellyfish.Virtu.Services
}
}
public void Reset()
{
Buffer.BlockCopy(SampleZero, 0, _buffer, 0, SampleSize);
}
public override void Stop() // main thread
{
_readEvent.Set(); // signal events; avoids deadlock
@ -49,7 +54,9 @@ namespace Jellyfish.Virtu.Services
public const int SampleChannels = 1;
public const int SampleBits = 8;
public const int SampleLatency = 40; // ms
public const int SampleSize = (int)(SampleRate * SampleLatency / 1000f) * SampleChannels * SampleBits / 8;
public const int SampleSize = (SampleRate * SampleLatency / 1000) * SampleChannels * (SampleBits / 8);
private static readonly byte[] SampleZero = new byte[SampleSize];
private byte[] _buffer = new byte[SampleSize];
private int _index;

View File

@ -56,7 +56,7 @@
Paddle0 = Paddle1 = Paddle2 = Paddle3 = 255; // not connected
}
public virtual void Update() { }
public virtual void Update() { } // main thread
public int Paddle0 { get; protected set; }
public int Paddle1 { get; protected set; }

View File

@ -30,6 +30,24 @@ namespace Jellyfish.Virtu.Services
public abstract bool IsKeyDown(int key);
public virtual void Update() // main thread
{
if (IsResetKeyDown)
{
if (!_resetKeyDown)
{
_resetKeyDown = true; // entering reset; pause until key released
Machine.Pause();
Machine.Reset();
}
}
else if (_resetKeyDown)
{
_resetKeyDown = false; // leaving reset
Machine.Unpause();
}
}
protected void OnAsciiKeyDown(int asciiKey)
{
EventHandler<AsciiKeyEventArgs> handler = AsciiKeyDown;
@ -39,33 +57,14 @@ namespace Jellyfish.Virtu.Services
}
}
public abstract void Update();
public void WaitForKeyUp()
{
while (IsAnyKeyDown)
{
Thread.Sleep(10);
}
}
public void WaitForResetKeyUp()
{
while (IsResetKeyDown)
{
Thread.Sleep(10);
}
}
public event EventHandler<AsciiKeyEventArgs> AsciiKeyDown;
public bool IsAnyKeyDown { get; protected set; }
public bool IsOpenAppleKeyDown { get; protected set; }
public bool IsCloseAppleKeyDown { get; protected set; }
public bool IsResetKeyDown { get; protected set; }
public bool IsCpuThrottleKeyDown { get; protected set; }
public bool IsVideoFullScreenKeyDown { get; protected set; }
public bool IsVideoMonochromeKeyDown { get; protected set; }
protected bool IsResetKeyDown { get; set; }
private bool _resetKeyDown;
}
}

View File

@ -8,7 +8,7 @@
}
public abstract void SetPixel(int x, int y, uint color);
public abstract void Update();
public abstract void Update(); // main thread
public void ToggleFullScreen()
{

View File

@ -6,13 +6,16 @@
xmlns:jv="clr-namespace:Jellyfish.Virtu;assembly=Jellyfish.Virtu">
<tk:DockPanel Background="Black">
<StackPanel Orientation="Horizontal" tk:DockPanel.Dock="Top">
<Button x:Name="_disk1Button" Content="Disk 1" IsTabStop="false" Margin="4 4 0 4"/>
<Button x:Name="_disk2Button" Content="Disk 2" IsTabStop="false" Margin="4 4 0 4"/>
<Button x:Name="_disk1Button" Content="Disk 1" IsTabStop="False" Margin="4 4 0 4"/>
<Button x:Name="_disk2Button" Content="Disk 2" IsTabStop="False" Margin="4 4 0 4"/>
<jl:FrameRateCounter Margin="4 4 0 4" VerticalAlignment="Center"/>
</StackPanel>
<Grid Cursor="None">
<Grid>
<Image x:Name="_image" MinWidth="560" MinHeight="384"/>
<MediaElement x:Name="_media"/>
<!--<ScrollViewer BorderThickness="0" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debug" FontFamily="Consolas" FontSize="12" Foreground="White"/>
</ScrollViewer>-->
</Grid>
</tk:DockPanel>
</UserControl>

View File

@ -26,8 +26,16 @@ namespace Jellyfish.Virtu.Services
//_page.Closed += (sender, e) => _media.Stop(); // SL is missing Closed / Unloaded event
}
private void OnMediaSourceUpdate(object sender, WaveMediaStreamSourceUpdateEventArgs e)
private void OnMediaSourceUpdate(object sender, WaveMediaStreamSourceUpdateEventArgs e) // audio thread
{
//if (_count++ % (1000 / SampleLatency) == 0)
//{
// _page.Dispatcher.BeginInvoke(new Action(() =>
// {
// ((MainPage)_page)._debug.Text += string.Concat(DateTime.Now, " OnMediaSourceUpdate", Environment.NewLine);
// }));
//}
Update(e.BufferSize, (source, count) =>
{
Buffer.BlockCopy(source, 0, e.Buffer, 0, count);
@ -37,5 +45,6 @@ namespace Jellyfish.Virtu.Services
private UserControl _page;
private MediaElement _media;
private WaveMediaStreamSource _mediaSource = new WaveMediaStreamSource(SampleRate, SampleChannels, SampleBits, SampleSize, SampleLatency);
//private int _count;
}
}

View File

@ -29,7 +29,7 @@ namespace Jellyfish.Virtu.Services
return IsKeyDown((Key)key);
}
public override void Update()
public override void Update() // main thread
{
if (_updateAnyKeyDown) // SL is missing access to keyboard state; could lose track of keyboard state after Alt+Tab
{
@ -46,15 +46,13 @@ namespace Jellyfish.Virtu.Services
}
ModifierKeys modifiers = System.Windows.Input.Keyboard.Modifiers;
IsOpenAppleKeyDown = ((modifiers & (ModifierKeys.Control | ModifierKeys.Alt)) == (ModifierKeys.Control | ModifierKeys.Alt)) ||
(((modifiers & ModifierKeys.Control) != 0) && IsKeyDown(Key.Left));
IsCloseAppleKeyDown = ((modifiers & (ModifierKeys.Control | ModifierKeys.Windows)) == (ModifierKeys.Control | ModifierKeys.Windows)) ||
(((modifiers & ModifierKeys.Control) != 0) && IsKeyDown(Key.Right));
IsResetKeyDown = ((modifiers & ModifierKeys.Control) != 0) && (IsKeyDown(Key.F12) || IsKeyDown(Key.Up));
bool control = ((modifiers & ModifierKeys.Control) != 0);
IsCpuThrottleKeyDown = IsKeyDown(Key.F8);
IsVideoFullScreenKeyDown = IsKeyDown(Key.F11);
IsVideoMonochromeKeyDown = IsKeyDown(Key.F9);
IsOpenAppleKeyDown = ((modifiers & ModifierKeys.Alt) != 0) || IsKeyDown(Key.NumPad0);
IsCloseAppleKeyDown = ((modifiers & ModifierKeys.Windows) != 0) || IsKeyDown(Key.Decimal);
IsResetKeyDown = control && IsKeyDown(Key.Back);
base.Update();
}
private bool IsKeyDown(Key key)
@ -64,7 +62,10 @@ namespace Jellyfish.Virtu.Services
private void OnPageKeyDown(object sender, KeyEventArgs e)
{
//((MainPage)_page)._debug.Text += string.Concat("OnPageKeyDn: Key=", e.Key, " PlatformKeyCode=", e.PlatformKeyCode, Environment.NewLine);
_states[(int)e.Key] = true;
_updateAnyKeyDown = false;
IsAnyKeyDown = true;
int asciiKey = GetAsciiKey(e.Key, e.PlatformKeyCode);
@ -73,13 +74,38 @@ namespace Jellyfish.Virtu.Services
OnAsciiKeyDown(asciiKey);
e.Handled = true;
}
Update();
}
private void OnPageKeyUp(object sender, KeyEventArgs e)
{
_capsLock ^= (e.Key == Key.CapsLock); // SL is missing caps lock support; try to track manually
//((MainPage)_page)._debug.Text += string.Concat("OnPageKeyUp: Key=", e.Key, " PlatformKeyCode=", e.PlatformKeyCode, Environment.NewLine);
_states[(int)e.Key] = false;
_updateAnyKeyDown = true;
ModifierKeys modifiers = System.Windows.Input.Keyboard.Modifiers;
bool control = ((modifiers & ModifierKeys.Control) != 0);
if (e.Key == Key.CapsLock)
{
_capsLock ^= true; // SL is missing caps lock support; try to track manually
}
else if (control && (e.Key == Key.Divide))
{
Machine.Cpu.ToggleThrottle();
}
else if (control && (e.Key == Key.Multiply))
{
Machine.Video.ToggleMonochrome();
}
else if (control && (e.Key == Key.Subtract))
{
Machine.Video.ToggleFullScreen();
}
Update();
}
private void OnPageLostFocus(object sender, RoutedEventArgs e) // reset keyboard state on lost focus; can't access keyboard state on got focus
@ -124,7 +150,7 @@ namespace Jellyfish.Virtu.Services
return 0x1B;
case Key.Back:
return 0x7F;
return control ? -1 : 0x7F;
case Key.Space:
return ' ';
@ -355,51 +381,6 @@ namespace Jellyfish.Virtu.Services
break;
}
break;
case Key.NumPad1:
return '1';
case Key.NumPad2:
return '2';
case Key.NumPad3:
return '3';
case Key.NumPad4:
return '4';
case Key.NumPad5:
return '5';
case Key.NumPad6:
return '6';
case Key.NumPad7:
return '7';
case Key.NumPad8:
return '8';
case Key.NumPad9:
return '9';
case Key.NumPad0:
return '0';
case Key.Decimal:
return '.';
case Key.Divide:
return '/';
case Key.Multiply:
return '*';
case Key.Subtract:
return '-';
case Key.Add:
return '+';
}
return -1;

View File

@ -32,7 +32,7 @@ namespace Jellyfish.Virtu.Services
_pixelsDirty = true;
}
public override void Update()
public override void Update() // main thread
{
if (Application.Current.IsRunningOutOfBrowser && /*_window.IsActive &&*/ (_isFullScreen != IsFullScreen))
{

View File

@ -18,6 +18,13 @@ namespace Jellyfish.Virtu
Machine.Events.AddEvent(CyclesPerFlush * Machine.Settings.Cpu.Multiplier, _flushOutputEvent);
}
public override void Reset()
{
_audioService.Reset();
_isHigh = false;
_highCycles = _totalCycles = 0;
}
public void ToggleOutput()
{
UpdateCycles();

View File

@ -5,12 +5,15 @@
Title="Virtu" ResizeMode="CanMinimize" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen">
<DockPanel Background="Black">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<Button x:Name="_disk1Button" Content="Disk 1" Focusable="false" IsTabStop="false" Margin="4 4 0 4"/>
<Button x:Name="_disk2Button" Content="Disk 2" Focusable="false" IsTabStop="false" Margin="4 4 0 4"/>
<Button x:Name="_disk1Button" Content="Disk 1" Focusable="False" IsTabStop="False" Margin="4 4 0 4"/>
<Button x:Name="_disk2Button" Content="Disk 2" Focusable="False" IsTabStop="False" Margin="4 4 0 4"/>
<jl:FrameRateCounter Margin="4 4 0 4" VerticalAlignment="Center"/>
</StackPanel>
<Grid Cursor="None">
<Grid>
<Image x:Name="_image" MinWidth="560" MinHeight="384" RenderOptions.BitmapScalingMode="NearestNeighbor"/>
<!--<ScrollViewer BorderThickness="0" Focusable="False" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debug" FontFamily="Consolas" FontSize="12" Foreground="White"/>
</ScrollViewer>-->
</Grid>
</DockPanel>
</Window>

View File

@ -32,8 +32,16 @@ namespace Jellyfish.Virtu.Services
base.Dispose(disposing);
}
private void OnDirectSoundUpdate(object sender, DirectSoundUpdateEventArgs e)
private void OnDirectSoundUpdate(object sender, DirectSoundUpdateEventArgs e) // audio thread
{
//if (_count++ % (1000 / SampleLatency) == 0)
//{
// _window.Dispatcher.BeginInvoke(new Action(() =>
// {
// ((MainWindow)_window)._debug.Text += string.Concat(DateTime.Now, " OnDirectSoundUpdate", Environment.NewLine);
// }));
//}
Update(e.BufferSize, (source, count) =>
{
Marshal.Copy(source, 0, e.Buffer, count);
@ -42,5 +50,6 @@ namespace Jellyfish.Virtu.Services
private Window _window;
private DirectSound _directSound = new DirectSound(SampleRate, SampleChannels, SampleBits, SampleSize);
//private int _count;
}
}

View File

@ -28,7 +28,7 @@ namespace Jellyfish.Virtu.Services
return IsKeyDown((Key)key);
}
public override void Update()
public override void Update() // main thread
{
KeyboardDevice keyboard = System.Windows.Input.Keyboard.PrimaryDevice;
if (_updateAnyKeyDown)
@ -46,14 +46,13 @@ namespace Jellyfish.Virtu.Services
}
}
ModifierKeys modifiers = keyboard.Modifiers;
IsOpenAppleKeyDown = keyboard.IsKeyDown(Key.LeftAlt);
IsCloseAppleKeyDown = keyboard.IsKeyDown(Key.RightAlt);
IsResetKeyDown = ((modifiers & ModifierKeys.Control) != 0) && keyboard.IsKeyDown(Key.F12);
bool control = ((keyboard.Modifiers & ModifierKeys.Control) != 0);
IsCpuThrottleKeyDown = keyboard.IsKeyDown(Key.F8);
IsVideoFullScreenKeyDown = keyboard.IsKeyDown(Key.F11);
IsVideoMonochromeKeyDown = keyboard.IsKeyDown(Key.F9);
IsOpenAppleKeyDown = keyboard.IsKeyDown(Key.LeftAlt) || IsKeyDown(Key.NumPad0);
IsCloseAppleKeyDown = keyboard.IsKeyDown(Key.RightAlt) || IsKeyDown(Key.Decimal);
IsResetKeyDown = control && keyboard.IsKeyDown(Key.Back);
base.Update();
}
private bool IsKeyDown(Key key)
@ -63,7 +62,10 @@ namespace Jellyfish.Virtu.Services
private void OnWindowKeyDown(object sender, KeyEventArgs e)
{
//((MainWindow)_window)._debug.Text += string.Concat("OnWindowKeyDn: Key=", e.Key, Environment.NewLine);
_states[(int)((e.Key == Key.System) ? e.SystemKey : e.Key)] = true;
_updateAnyKeyDown = false;
IsAnyKeyDown = true;
int asciiKey = GetAsciiKey(e.Key, e.KeyboardDevice);
@ -72,12 +74,33 @@ namespace Jellyfish.Virtu.Services
OnAsciiKeyDown(asciiKey);
e.Handled = true;
}
Update();
}
private void OnWindowKeyUp(object sender, KeyEventArgs e)
{
//((MainWindow)_window)._debug.Text += string.Concat("OnWindowKeyUp: Key=", e.Key, Environment.NewLine);
_states[(int)((e.Key == Key.System) ? e.SystemKey : e.Key)] = false;
_updateAnyKeyDown = true;
bool control = ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0);
if (control && (e.Key == Key.Divide))
{
Machine.Cpu.ToggleThrottle();
}
else if (control && (e.Key == Key.Multiply))
{
Machine.Video.ToggleMonochrome();
}
else if (control && (e.Key == Key.Subtract))
{
Machine.Video.ToggleFullScreen();
}
Update();
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
@ -112,7 +135,7 @@ namespace Jellyfish.Virtu.Services
return 0x1B;
case Key.Back:
return 0x7F;
return control ? -1 : 0x7F;
case Key.Space:
return ' ';
@ -257,51 +280,6 @@ namespace Jellyfish.Virtu.Services
case Key.OemPeriod:
return shift ? '>' : '.';
case Key.NumPad1:
return '1';
case Key.NumPad2:
return '2';
case Key.NumPad3:
return '3';
case Key.NumPad4:
return '4';
case Key.NumPad5:
return '5';
case Key.NumPad6:
return '6';
case Key.NumPad7:
return '7';
case Key.NumPad8:
return '8';
case Key.NumPad9:
return '9';
case Key.NumPad0:
return '0';
case Key.Decimal:
return '.';
case Key.Divide:
return '/';
case Key.Multiply:
return '*';
case Key.Subtract:
return '-';
case Key.Add:
return '+';
}
return -1;

View File

@ -40,7 +40,7 @@ namespace Jellyfish.Virtu.Services
_pixelsDirty = true;
}
public override void Update()
public override void Update() // main thread
{
if (_window.IsActive && (_isFullScreen != IsFullScreen))
{

View File

@ -7,7 +7,7 @@ namespace Jellyfish.Virtu
{
public sealed class MainGame : GameBase
{
public MainGame() :
public MainGame() :
base("Virtu")
{
Components.Add(new FrameRateCounter(this) { DrawOrder = 1, FontName = "Consolas" });
@ -46,6 +46,7 @@ namespace Jellyfish.Virtu
_audioService.Dispose();
_videoService.Dispose();
}
base.Dispose(disposing);
}
@ -58,6 +59,7 @@ namespace Jellyfish.Virtu
{
_keyboardService.Update();
_gamePortService.Update();
base.Update(gameTime);
}
@ -65,6 +67,7 @@ namespace Jellyfish.Virtu
{
GraphicsDevice.Clear(Color.Black);
_videoService.Update();
base.Draw(gameTime);
}

View File

@ -30,7 +30,7 @@ namespace Jellyfish.Virtu.Services
}
}
private void OnDirectSoundUpdate(object sender, DirectSoundUpdateEventArgs e)
private void OnDirectSoundUpdate(object sender, DirectSoundUpdateEventArgs e) // audio thread
{
Update(e.BufferSize, (source, count) =>
{

View File

@ -10,7 +10,7 @@ namespace Jellyfish.Virtu.Services
{
}
public override void Update()
public override void Update() // main thread
{
_lastState = _state;
_state = GamePad.GetState(PlayerIndex.One);

View File

@ -18,14 +18,14 @@ namespace Jellyfish.Virtu.Services
return IsKeyDown((Keys)key);
}
public override void Update()
public override void Update() // main thread
{
#if XBOX
GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
#endif
_lastState = _state;
_state = Microsoft.Xna.Framework.Input.Keyboard.GetState();
GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
bool gamePadControl = (gamePadState.Buttons.LeftStick == ButtonState.Pressed);
if (_state != _lastState)
{
IsAnyKeyDown = false;
@ -36,25 +36,22 @@ namespace Jellyfish.Virtu.Services
IsAnyKeyDown = true;
if (!_lastState.IsKeyDown(key))
{
_capsLock ^= (key == Keys.CapsLock);
_lastKey = key;
_lastTime = DateTime.UtcNow.Ticks;
_repeatTime = RepeatDelay;
#if XBOX
int asciiKey = GetAsciiKey(key, ref gamePadState);
#else
int asciiKey = GetAsciiKey(key);
#endif
if (asciiKey >= 0)
{
OnAsciiKeyDown(asciiKey);
}
OnKeyDown(key, gamePadControl);
}
}
else if (key == _lastKey)
else
{
_lastKey = Keys.None;
if (key == _lastKey)
{
_lastKey = Keys.None;
}
if (_lastState.IsKeyDown(key))
{
OnKeyUp(key, gamePadControl);
}
}
}
}
@ -66,34 +63,17 @@ namespace Jellyfish.Virtu.Services
{
_lastTime = time;
_repeatTime = RepeatSpeed;
#if XBOX
int asciiKey = GetAsciiKey(_lastKey, ref gamePadState);
#else
int asciiKey = GetAsciiKey(_lastKey);
#endif
if (asciiKey >= 0)
{
OnAsciiKeyDown(asciiKey);
}
OnKeyDown(_lastKey, gamePadControl);
}
}
#if XBOX
IsOpenAppleKeyDown = IsKeyDown(Keys.LeftAlt) || (gamePadState.Buttons.LeftShoulder == ButtonState.Pressed);
IsCloseAppleKeyDown = IsKeyDown(Keys.RightAlt) || (gamePadState.Buttons.RightShoulder == ButtonState.Pressed);
IsResetKeyDown = ((IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl)) && IsKeyDown(Keys.F12)) ||
((gamePadState.Buttons.LeftStick == ButtonState.Pressed) && (gamePadState.Buttons.Start == ButtonState.Pressed));
IsCpuThrottleKeyDown = IsKeyDown(Keys.F8) || ((IsKeyDown(Keys.ChatPadGreen) || IsKeyDown(Keys.ChatPadOrange)) && IsKeyDown(Keys.D8));
IsVideoMonochromeKeyDown = IsKeyDown(Keys.F9) || ((IsKeyDown(Keys.ChatPadGreen) || IsKeyDown(Keys.ChatPadOrange)) && IsKeyDown(Keys.D9));
#else
IsOpenAppleKeyDown = IsKeyDown(Keys.LeftAlt);
IsCloseAppleKeyDown = IsKeyDown(Keys.RightAlt);
IsResetKeyDown = (IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl)) && IsKeyDown(Keys.F12);
bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl);
IsCpuThrottleKeyDown = IsKeyDown(Keys.F8);
IsVideoFullScreenKeyDown = IsKeyDown(Keys.F11);
IsVideoMonochromeKeyDown = IsKeyDown(Keys.F9);
#endif
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 = (control && IsKeyDown(Keys.Back)) || (gamePadControl && (gamePadState.Buttons.Start == ButtonState.Pressed));
base.Update();
}
private bool IsKeyDown(Keys key)
@ -101,17 +81,42 @@ namespace Jellyfish.Virtu.Services
return _state.IsKeyDown(key);
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
#if XBOX
private int GetAsciiKey(Keys key, ref GamePadState gamePadState)
private void OnKeyDown(Keys key, bool gamePadControl)
{
bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl) || (gamePadState.Buttons.LeftStick == ButtonState.Pressed);
#else
private int GetAsciiKey(Keys key)
int asciiKey = GetAsciiKey(key, gamePadControl);
if (asciiKey >= 0)
{
OnAsciiKeyDown(asciiKey);
}
}
private void OnKeyUp(Keys key, bool gamePadControl)
{
bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl);
#endif
if (key == Keys.CapsLock)
{
_capsLock ^= true;
}
else if ((control && (key == Keys.Divide)) || (gamePadControl && (key == Keys.D8)))
{
Machine.Cpu.ToggleThrottle();
}
else if ((control && (key == Keys.Multiply)) || (gamePadControl && (key == Keys.D9)))
{
Machine.Video.ToggleMonochrome();
}
else if ((control && (key == Keys.Subtract)) || (gamePadControl && (key == Keys.D0)))
{
Machine.Video.ToggleFullScreen();
}
}
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]
private int GetAsciiKey(Keys key, bool gamePadControl)
{
bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl) || gamePadControl;
bool shift = IsKeyDown(Keys.LeftShift) || IsKeyDown(Keys.RightShift);
bool capsLock = shift ^ _capsLock;
bool green = IsKeyDown(Keys.ChatPadGreen);
@ -141,7 +146,7 @@ namespace Jellyfish.Virtu.Services
return 0x1B;
case Keys.Back:
return 0x7F;
return control ? -1 : 0x7F;
case Keys.Space:
return ' ';
@ -168,13 +173,13 @@ namespace Jellyfish.Virtu.Services
return shift ? '&' : '7';
case Keys.D8:
return shift ? '*' : '8';
return gamePadControl ? -1 : shift ? '*' : '8';
case Keys.D9:
return shift ? '(' : '9';
return gamePadControl ? -1 : shift ? '(' : '9';
case Keys.D0:
return shift ? ')' : '0';
return gamePadControl ? -1 : shift ? ')' : '0';
case Keys.A:
return control ? 0x01 : green ? '~' : capsLock ? 'A' : 'a';
@ -287,51 +292,6 @@ namespace Jellyfish.Virtu.Services
case Keys.OemPeriod:
return shift ? '>' : green ? '?' : '.';
case Keys.NumPad1:
return '1';
case Keys.NumPad2:
return '2';
case Keys.NumPad3:
return '3';
case Keys.NumPad4:
return '4';
case Keys.NumPad5:
return '5';
case Keys.NumPad6:
return '6';
case Keys.NumPad7:
return '7';
case Keys.NumPad8:
return '8';
case Keys.NumPad9:
return '9';
case Keys.NumPad0:
return '0';
case Keys.Decimal:
return '.';
case Keys.Divide:
return '/';
case Keys.Multiply:
return '*';
case Keys.Subtract:
return '-';
case Keys.Add:
return '+';
}
return -1;

View File

@ -30,7 +30,7 @@ namespace Jellyfish.Virtu.Services
_pixelsDirty = true;
}
public override void Update()
public override void Update() // main thread
{
if (_game.GraphicsDeviceManager.IsFullScreen != IsFullScreen)
{