Upgraded to Windows Phone 7 Beta.

Upgraded to FxCop 10.0.
Dropped Silverlight Toolkit dependency (for now).
Modified AudioService to avoid deadlocks by using timeouts.
Refactored DebugService and implementations.
Modified SilverlightVideoService to handle browser zoom.
Split Wpf MainWindow into MainPage child control.

--HG--
extra : convert_revision : svn%3Affd33b8c-2492-42e0-bdc5-587b920b7d6d/trunk%4048619
This commit is contained in:
Sean Fausett 2010-07-16 09:36:41 +00:00
parent 9fca4b220f
commit 2167383a00
57 changed files with 651 additions and 1023 deletions

View File

@ -0,0 +1,52 @@
using System;
using System.Windows.Threading;
namespace Jellyfish.Library
{
public static class DispatcherExtensions
{
public static void CheckBeginInvoke(this Dispatcher dispatcher, Action action)
{
if (dispatcher == null)
{
throw new ArgumentNullException("dispatcher");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
if (dispatcher.CheckAccess())
{
action();
}
else
{
dispatcher.BeginInvoke(action);
}
}
#if WINDOWS
public static void CheckInvoke(this Dispatcher dispatcher, Action action)
{
if (dispatcher == null)
{
throw new ArgumentNullException("dispatcher");
}
if (action == null)
{
throw new ArgumentNullException("action");
}
if (dispatcher.CheckAccess())
{
action();
}
else
{
dispatcher.Invoke(action);
}
}
#endif
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FxCopProject Version="1.36" Name="My FxCop Project">
<FxCopProject Version="10.0" Name="Jellyfish.Library">
<ProjectOptions>
<SharedProject>True</SharedProject>
<Stylesheet Apply="False">c:\program files\microsoft fxcop 1.36\Xml\FxCopReport.xsl</Stylesheet>
<Stylesheet Apply="False">$(FxCopDir)\Xml\FxCopReport.xsl</Stylesheet>
<SaveMessages>
<Project Status="Active, Excluded" NewOnly="False" />
<Report Status="Active" NewOnly="False" />
@ -19,11 +19,10 @@
<SearchGlobalAssemblyCache>True</SearchGlobalAssemblyCache>
<DeadlockDetectionTimeout>120</DeadlockDetectionTimeout>
<IgnoreGeneratedCode>True</IgnoreGeneratedCode>
<TargetFrameworkVersion>3.5</TargetFrameworkVersion>
</ProjectOptions>
<Targets>
<Target Name="$(ProjectDir)/Wpf/bin/Jellyfish.Library.dll" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Xna/bin/Jellyfish.Library.dll" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Xna/bin/x86/Jellyfish.Library.dll" Analyze="True" AnalyzeAllChildren="True" />
</Targets>
<Rules>
<RuleFiles>
@ -35,10 +34,11 @@
<RuleFile Name="$(FxCopDir)\Rules\PerformanceRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\PortabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\SecurityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\SecurityTransparencyRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\UsageRules.dll" Enabled="True" AllRulesEnabled="True" />
</RuleFiles>
<Groups />
<Settings />
</Rules>
<FxCopReport Version="1.36" />
<FxCopReport Version="10.0" />
</FxCopProject>

View File

@ -1,6 +1,11 @@
using System;
using System.Diagnostics;
using System.Text;
using System.Windows;
#if WINDOWS_PHONE
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
#endif
namespace Jellyfish.Library
{
@ -19,24 +24,25 @@ namespace Jellyfish.Library
//AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException;
}
private void OnApplicationUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
#if WINDOWS_PHONE
protected void InitializePhoneApplication()
{
MessageBox.Show(GetExceptionMessage(e.ExceptionObject), GetExceptionCaption("Application Exception"), MessageBoxButton.OK);
e.Handled = true;
if (!_phoneApplicationInitialized)
{
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += OnRootFrameNavigated;
RootFrame.NavigationFailed += OnRootFrameNavigationFailed;
_phoneApplicationInitialized = true;
}
}
//private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
//{
// MessageBox.Show(GetExceptionMessage(e.ExceptionObject as Exception), GetExceptionCaption("AppDomain Exception", e.IsTerminating), MessageBoxButton.OK);
//}
#endif
private string GetExceptionCaption(string title, bool isTerminating = false)
{
var caption = new StringBuilder();
if (!string.IsNullOrEmpty(Name))
{
caption.Append(Name);
caption.Append(" ");
caption.Append(Name).Append(' ');
}
caption.Append(title);
if (isTerminating)
@ -47,19 +53,48 @@ namespace Jellyfish.Library
return caption.ToString();
}
private static string GetExceptionMessage(Exception exception)
private void OnApplicationUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
var message = new StringBuilder();
if (exception != null)
MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("Application Exception"), MessageBoxButton.OK);
if (Debugger.IsAttached)
{
message.Append(exception.Message.ToString());
message.Append(Environment.NewLine);
message.Append(exception.StackTrace.ToString());
Debugger.Break();
}
return message.ToString();
}
//private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
//{
// MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating), MessageBoxButton.OK);
// if (Debugger.IsAttached)
// {
// Debugger.Break();
// }
//}
#if WINDOWS_PHONE
private void OnRootFrameNavigated(object sender, NavigationEventArgs e)
{
if (RootVisual != RootFrame)
{
RootVisual = RootFrame;
}
RootFrame.Navigated -= OnRootFrameNavigated;
}
private void OnRootFrameNavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
#endif
public string Name { get; private set; }
#if WINDOWS_PHONE
public PhoneApplicationFrame RootFrame { get; private set; }
private bool _phoneApplicationInitialized;
#endif
}
}

View File

@ -67,6 +67,9 @@
<Compile Include="..\AssemblyCommentAttribute.cs">
<Link>AssemblyCommentAttribute.cs</Link>
</Compile>
<Compile Include="..\DispatcherExtensions.cs">
<Link>DispatcherExtensions.cs</Link>
</Compile>
<Compile Include="..\FrameRateCounter.xaml.cs">
<Link>FrameRateCounter.xaml.cs</Link>
<DependentUpon>FrameRateCounter.xaml</DependentUpon>
@ -89,6 +92,12 @@
<Compile Include="..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\WaveFormat.cs">
<Link>WaveFormat.cs</Link>
</Compile>

View File

@ -47,6 +47,7 @@
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Phone" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
@ -59,6 +60,9 @@
<Compile Include="..\..\AssemblyCommentAttribute.cs">
<Link>AssemblyCommentAttribute.cs</Link>
</Compile>
<Compile Include="..\..\DispatcherExtensions.cs">
<Link>DispatcherExtensions.cs</Link>
</Compile>
<Compile Include="..\..\GlobalSuppressions.cs">
<Link>GlobalSuppressions.cs</Link>
</Compile>
@ -77,6 +81,12 @@
<Compile Include="..\..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\..\WaveFormat.cs">
<Link>WaveFormat.cs</Link>
</Compile>

View File

@ -0,0 +1,23 @@
using System;
using System.Threading;
namespace Jellyfish.Library
{
public static class ThreadExtensions
{
public static void IsAliveJoin(this Thread thread)
{
if (thread == null)
{
throw new ArgumentNullException("thread");
}
#if !XBOX
if (thread.IsAlive)
#endif
{
thread.Join();
}
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Threading;
namespace Jellyfish.Library
{
public static class WaitHandleExtensions
{
#if XBOX
public static bool WaitOne(this WaitHandle waitHandle, int millisecondsTimeout)
{
if (waitHandle == null)
{
throw new ArgumentNullException("waitHandle");
}
return waitHandle.WaitOne(millisecondsTimeout, false);
}
#endif
}
}

View File

@ -24,26 +24,12 @@ namespace Jellyfish.Library
AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException;
}
private void OnApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(GetExceptionMessage(e.Exception), GetExceptionCaption("Application Dispatcher Exception", isTerminating: true));
e.Handled = true;
Shutdown();
}
private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(GetExceptionMessage(e.ExceptionObject as Exception), GetExceptionCaption("AppDomain Exception", e.IsTerminating));
}
private string GetExceptionCaption(string title, bool isTerminating = false)
{
var caption = new StringBuilder();
caption.AppendFormat("[{0}] ", Process.GetCurrentProcess().Id);
if (!string.IsNullOrEmpty(Name))
{
caption.Append(Name);
caption.Append(" ");
caption.Append(Name).Append(' ');
}
caption.Append(title);
if (isTerminating)
@ -54,17 +40,24 @@ namespace Jellyfish.Library
return caption.ToString();
}
private static string GetExceptionMessage(Exception exception)
private void OnApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
var message = new StringBuilder();
if (exception != null)
MessageBox.Show(e.Exception.ToString(), GetExceptionCaption("Application Dispatcher Exception", isTerminating: true));
if (Debugger.IsAttached)
{
message.Append(exception.Message.ToString());
message.Append(Environment.NewLine);
message.Append(exception.StackTrace.ToString());
Debugger.Break();
}
e.Handled = true;
Shutdown();
}
return message.ToString();
private void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show(e.ExceptionObject.ToString(), GetExceptionCaption("AppDomain Exception", e.IsTerminating));
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
public string Name { get; private set; }

View File

@ -58,6 +58,9 @@
<Compile Include="..\DirectSoundInterop.cs">
<Link>DirectSoundInterop.cs</Link>
</Compile>
<Compile Include="..\DispatcherExtensions.cs">
<Link>DispatcherExtensions.cs</Link>
</Compile>
<Compile Include="..\FrameRateCounter.xaml.cs">
<Link>FrameRateCounter.xaml.cs</Link>
<DependentUpon>FrameRateCounter.xaml</DependentUpon>
@ -95,6 +98,12 @@
<Compile Include="..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\WaveFormat.cs">
<Link>WaveFormat.cs</Link>
</Compile>

View File

@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@ -12,12 +13,6 @@ namespace Jellyfish.Library
{
FontColor = Color.White;
FontName = "Default";
//game.IsFixedTimeStep = true; // fixed (default)
//game.TargetElapsedTime = TimeSpan.FromSeconds(1 / 60f);
//game.IsFixedTimeStep = false; // flatout
//game.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
}
protected override void LoadContent()
@ -29,6 +24,7 @@ namespace Jellyfish.Library
Position = new Vector2(titleSafeArea.X, titleSafeArea.Y);
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public override void Draw(GameTime gameTime)
{
_frameCount++;
@ -44,6 +40,7 @@ namespace Jellyfish.Library
_spriteBatch.End();
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public override void Update(GameTime gameTime)
{
if (gameTime == null)

View File

@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
@ -16,16 +17,21 @@ namespace Jellyfish.Library
{
Name = name;
Content.RootDirectory = "Content";
GraphicsDeviceManager = new GraphicsDeviceManager(this);
#if WINDOWS_PHONE
GraphicsDeviceManager.IsFullScreen = true;
TargetElapsedTime = TimeSpan.FromTicks(333333); // 30 fps
#endif
GraphicsDeviceService = (IGraphicsDeviceService)Services.GetService(typeof(IGraphicsDeviceService));
Content.RootDirectory = "Content";
if (!string.IsNullOrEmpty(Name))
{
Window.Title = Name;
}
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
protected override void Update(GameTime gameTime)
{
var gamePadState = GamePad.GetState(PlayerIndex.One);

View File

@ -110,6 +110,12 @@
<Compile Include="..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\XmlSerializerHelpers.cs">
<Link>XmlSerializerHelpers.cs</Link>
</Compile>

View File

@ -122,6 +122,12 @@
<Compile Include="..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\XmlSerializerHelpers.cs">
<Link>XmlSerializerHelpers.cs</Link>
</Compile>

View File

@ -134,6 +134,12 @@
<Compile Include="..\StringBuilderExtensions.cs">
<Link>StringBuilderExtensions.cs</Link>
</Compile>
<Compile Include="..\ThreadExtensions.cs">
<Link>ThreadExtensions.cs</Link>
</Compile>
<Compile Include="..\WaitHandleExtensions.cs">
<Link>WaitHandleExtensions.cs</Link>
</Compile>
<Compile Include="..\XmlSerializerHelpers.cs">
<Link>XmlSerializerHelpers.cs</Link>
</Compile>

View File

@ -1,7 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Threading;
namespace Jellyfish.Virtu
{

View File

@ -1,6 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Jellyfish.Virtu.Services;
using Jellyfish.Virtu.Settings;
namespace Jellyfish.Virtu
{

View File

@ -15,9 +15,7 @@ namespace Jellyfish.Virtu
DriveArmStepDelta[3] = new int[] { 0, 1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 1, -1, 0, -1, 0 }; // phase 3
}
#if !XBOX
[SecurityCritical]
#endif
public void InsertDisk(string fileName, bool isWriteProtected)
{
using (var stream = File.OpenRead(fileName))

View File

@ -2,7 +2,6 @@
using System.Diagnostics.CodeAnalysis;
using Jellyfish.Library;
using Jellyfish.Virtu.Services;
using Jellyfish.Virtu.Settings;
namespace Jellyfish.Virtu
{

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FxCopProject Version="1.36" Name="My FxCop Project">
<FxCopProject Version="10.0" Name="Jellyfish.Virtu">
<ProjectOptions>
<SharedProject>True</SharedProject>
<Stylesheet Apply="False">c:\program files\microsoft fxcop 1.36\Xml\FxCopReport.xsl</Stylesheet>
<Stylesheet Apply="False">$(FxCopDir)\Xml\FxCopReport.xsl</Stylesheet>
<SaveMessages>
<Project Status="Active, Excluded" NewOnly="False" />
<Report Status="Active" NewOnly="False" />
@ -19,11 +19,10 @@
<SearchGlobalAssemblyCache>True</SearchGlobalAssemblyCache>
<DeadlockDetectionTimeout>120</DeadlockDetectionTimeout>
<IgnoreGeneratedCode>True</IgnoreGeneratedCode>
<TargetFrameworkVersion>3.5</TargetFrameworkVersion>
</ProjectOptions>
<Targets>
<Target Name="$(ProjectDir)/Wpf/bin/Jellyfish.Virtu.exe" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Xna/bin/Jellyfish.Virtu.exe" Analyze="True" AnalyzeAllChildren="True" />
<Target Name="$(ProjectDir)/Xna/bin/x86/Jellyfish.Virtu.exe" Analyze="True" AnalyzeAllChildren="True" />
</Targets>
<Rules>
<RuleFiles>
@ -35,46 +34,11 @@
<RuleFile Name="$(FxCopDir)\Rules\PerformanceRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\PortabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\SecurityRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\SecurityTransparencyRules.dll" Enabled="True" AllRulesEnabled="True" />
<RuleFile Name="$(FxCopDir)\Rules\UsageRules.dll" Enabled="True" AllRulesEnabled="True" />
</RuleFiles>
<Groups />
<Settings />
</Rules>
<FxCopReport Version="1.36">
<Targets>
<Target Name="$(ProjectDir)/Wpf/bin/Jellyfish.Virtu.exe">
<Modules>
<Module Name="jellyfish.virtu.exe">
<Namespaces>
<Namespace Name="Jellyfish.Virtu">
<Types>
<Type Name="MainWindow">
<Members>
<Member Name="#System.Windows.Markup.IComponentConnector.Connect(System.Int32,System.Object)">
<Messages>
<Message TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800" Created="2009-12-11 09:07:49Z">
<Issue Name="Parameter">
<Item>'target'</Item>
<Item>'Button'</Item>
<Item>'MainWindow.IComponentConnector.Connect(int, object)'</Item>
<Item>castclass</Item>
</Issue>
</Message>
</Messages>
</Member>
</Members>
</Type>
</Types>
</Namespace>
</Namespaces>
</Module>
</Modules>
</Target>
</Targets>
<Rules>
<Rule TypeName="DoNotCastUnnecessarily" Category="Microsoft.Performance" CheckId="CA1800">
<Resolution Name="Parameter">{0}, a parameter, is cast to type {1} multiple times in method {2}. Cache the result of the 'as' operator or direct cast in order to eliminate the redundant {3} instruction.</Resolution>
</Rule>
</Rules>
</FxCopReport>
<FxCopReport Version="10.0" />
</FxCopProject>

View File

@ -47,8 +47,6 @@ namespace Jellyfish.Virtu
_storageService.Load(MachineSettings.FileName, stream => Settings.Deserialize(stream));
State = MachineState.Starting;
Services.ForEach(service => service.Start());
Thread.Start();
}
@ -68,14 +66,14 @@ namespace Jellyfish.Virtu
public void Stop()
{
State = MachineState.Stopping;
Services.ForEach(service => service.Stop());
_pauseEvent.Set();
_unpauseEvent.Set();
Thread.Join();
Thread.IsAliveJoin();
State = MachineState.Stopped;
_storageService.Save(MachineSettings.FileName, stream => Settings.Serialize(stream));
if (_storageService != null)
{
_storageService.Save(MachineSettings.FileName, stream => Settings.Serialize(stream));
}
}
private void Run() // machine thread

View File

@ -36,29 +36,33 @@ namespace Jellyfish.Virtu.Settings
Button0 = 0, Button1 = 0, Button2 = 0
}
};
#if WINDOWS_PHONE
Audio = new AudioSettings { Volume = 0.85 };
#else
Audio = new AudioSettings { Volume = 0.5 };
#endif
Video = new VideoSettings
{
IsFullScreen = false, IsMonochrome = false, ScannerOptions = ScannerOptions.None,
Color = new ColorSettings
{
Black = 0x000000,
DarkBlue = 0x000099,
DarkGreen = 0x117722,
MediumBlue = 0x0000FF,
Brown = 0x885500,
LightGrey = 0x99AAAA,
Green = 0x00EE11,
Aquamarine = 0x55FFAA,
DeepRed = 0xFF1111,
Purple = 0xDD00DD,
DarkGrey = 0x445555,
LightBlue = 0x33AAFF,
Orange = 0xFF4411,
Pink = 0xFF9988,
Yellow = 0xFFFF11,
White = 0xFFFFFF,
Monochrome = 0x00AA00
Black = 0xFF000000, // BGRA
DarkBlue = 0xFF000099,
DarkGreen = 0xFF117722,
MediumBlue = 0xFF0000FF,
Brown = 0xFF885500,
LightGrey = 0xFF99AAAA,
Green = 0xFF00EE11,
Aquamarine = 0xFF55FFAA,
DeepRed = 0xFFFF1111,
Purple = 0xFFDD00DD,
DarkGrey = 0xFF445555,
LightBlue = 0xFF33AAFF,
Orange = 0xFFFF4411,
Pink = 0xFFFF9988,
Yellow = 0xFFFFFF11,
White = 0xFFFFFFFF,
Monochrome = 0xFF00AA00
}
};
}

View File

@ -1,6 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
{
@ -21,7 +22,7 @@ namespace Jellyfish.Virtu.Services
_readEvent.Set();
if (Machine.Settings.Cpu.IsThrottled)
{
_writeEvent.WaitOne();
_writeEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock
}
}
}
@ -33,17 +34,11 @@ namespace Jellyfish.Virtu.Services
public abstract void SetVolume(double volume); // machine thread
public override void Stop() // main thread
{
_readEvent.Set(); // signal events; avoids deadlock
_writeEvent.Set();
}
protected void Update(int bufferSize, Action<byte[], int> updateBuffer) // audio thread
{
if (Machine.State == MachineState.Running)
{
_readEvent.WaitOne();
_readEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock
}
if (updateBuffer != null)
{

View File

@ -10,9 +10,14 @@ namespace Jellyfish.Virtu.Services
{
}
public virtual void WriteLine(string message)
public void WriteLine(string message)
{
Debug.WriteLine(string.Concat(DateTime.Now, " ", message));
OnWriteLine(string.Concat(DateTime.Now, ' ', message));
}
protected virtual void OnWriteLine(string message)
{
Debug.WriteLine(message);
}
}
}

View File

@ -1,6 +1,4 @@
using System;
namespace Jellyfish.Virtu.Services
namespace Jellyfish.Virtu.Services
{
public abstract class KeyboardService : MachineService
{

View File

@ -1,5 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace Jellyfish.Virtu.Services
{
@ -21,15 +20,6 @@ namespace Jellyfish.Virtu.Services
GC.SuppressFinalize(this);
}
public virtual void Start()
{
}
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Stop")]
public virtual void Stop()
{
}
protected virtual void Dispose(bool disposing)
{
}

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Jellyfish.Library;
using Jellyfish.Virtu.Properties;
namespace Jellyfish.Virtu.Services
@ -31,11 +30,6 @@ namespace Jellyfish.Virtu.Services
_serviceProviders.Add(serviceType, serviceProvider);
}
public void ForEach(Action<MachineService> action)
{
_serviceProviders.Values.ForEach(action);
}
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
public T GetService<T>()
{

View File

@ -72,7 +72,7 @@
<Reference Include="System.Net" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Browser" />
<Reference Include="System.Windows.Controls.Toolkit, Version=4.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Windows.Controls" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<Private>True</Private>

View File

@ -4,7 +4,7 @@
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library"
xmlns:jv="clr-namespace:Jellyfish.Virtu;assembly=Jellyfish.Virtu">
<Application.RootVisual>
<jv:MainPage/>
<jv:MainPage />
</Application.RootVisual>
<Application.Resources>
</Application.Resources>

View File

@ -1,21 +1,23 @@
<UserControl x:Class="Jellyfish.Virtu.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library"
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"/>
<jl:FrameRateCounter Margin="4 4 0 4" VerticalAlignment="Center"/>
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<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" />
</StackPanel>
<Grid>
<Image x:Name="_image" MinWidth="280" MinHeight="192"/>
<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"/>
<jl:FrameRateCounter Margin="0,0,4,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
<Grid Grid.Row="1">
<Image x:Name="_image" MinWidth="560" MinHeight="384" HorizontalAlignment="Center" VerticalAlignment="Center" />
<MediaElement x:Name="_media" />
<ScrollViewer x:Name="_debugScrollViewer" BorderThickness="0" IsTabStop="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debugText" FontFamily="Consolas" FontSize="12" Foreground="White" />
</ScrollViewer>
</Grid>
</tk:DockPanel>
</Grid>
</UserControl>

View File

@ -1,5 +1,5 @@
using System;
using System.IO;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
@ -13,26 +13,29 @@ namespace Jellyfish.Virtu
{
InitializeComponent();
_debugService = new SilverlightDebugService(_machine, this);
_storageService = new IsolatedStorageService(_machine);
_keyboardService = new SilverlightKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new SilverlightAudioService(_machine, this, _media);
_videoService = new SilverlightVideoService(_machine, this, _image);
if (!DesignerProperties.IsInDesignTool)
{
_debugService = new SilverlightDebugService(_machine, this);
_storageService = new IsolatedStorageService(_machine);
_keyboardService = new SilverlightKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new SilverlightAudioService(_machine, this, _media);
_videoService = new SilverlightVideoService(_machine, this, _image);
_machine.Services.AddService(typeof(DebugService), _debugService);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
_machine.Services.AddService(typeof(DebugService), _debugService);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
_disk1Button.Click += (sender, e) => OnDiskButtonClick(0);
_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
_disk1Button.Click += (sender, e) => OnDiskButtonClick(0);
_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
}
}
public void Dispose()
@ -46,6 +49,13 @@ namespace Jellyfish.Virtu
_videoService.Dispose();
}
public void WriteLine(string message)
{
_debugText.Text += message;
_debugScrollViewer.UpdateLayout();
_debugScrollViewer.ScrollToVerticalOffset(double.MaxValue);
}
private void OnCompositionTargetRendering(object sender, EventArgs e)
{
_keyboardService.Update();

View File

@ -54,8 +54,7 @@
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Phone.Controls" />
<Reference Include="Microsoft.Phone.Controls.Navigation" />
<Reference Include="Microsoft.Phone" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -1,566 +1,13 @@
<jl:ApplicationBase x:Class="Jellyfish.Virtu.MainApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:mpc="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library">
<!--RootFrame points to and loads the first page of your application-->
<Application.RootVisual>
<phoneNavigation:PhoneApplicationFrame x:Name="RootFrame" Source="/MainPage.xaml"/>
</Application.RootVisual>
<!-- Resources for following the Windows Phone design guidelines -->
<Application.Resources>
<!--************ THEME RESOURCES ************-->
<!-- Color Resources -->
<Color x:Key="PhoneBackgroundColor">#FF1F1F1F</Color>
<Color x:Key="PhoneContrastForegroundColor">Black</Color>
<Color x:Key="PhoneForegroundColor">White</Color>
<Color x:Key="PhoneInactiveColor">#FF666666</Color>
<Color x:Key="PhoneDisabledColor">#FF808080</Color>
<Color x:Key="PhoneSubtleColor">#FF999999</Color>
<Color x:Key="PhoneContrastBackgroundColor">#FFFFFFFF</Color>
<Color x:Key="PhoneTextBoxColor">#FFBFBFBF</Color>
<Color x:Key="PhoneBorderColor">#FFCCCCCC</Color>
<Color x:Key="PhoneTextSelectionColor">Black</Color>
<Color x:Key="PhoneAccentColor">#FF1BA1E2</Color>
<!-- Brush Resources -->
<SolidColorBrush x:Key="PhoneAccentBrush" Color="{StaticResource PhoneAccentColor}"/>
<SolidColorBrush x:Key="PhoneBackgroundBrush" Color="{StaticResource PhoneBackgroundColor}"/>
<SolidColorBrush x:Key="PhoneContrastForegroundBrush" Color="{StaticResource PhoneContrastForegroundColor}"/>
<SolidColorBrush x:Key="PhoneForegroundBrush" Color="{StaticResource PhoneForegroundColor}"/>
<SolidColorBrush x:Key="PhoneInactiveBrush" Color="{StaticResource PhoneInactiveColor}"/>
<SolidColorBrush x:Key="PhoneDisabledBrush" Color="{StaticResource PhoneDisabledColor}"/>
<SolidColorBrush x:Key="PhoneSubtleBrush" Color="{StaticResource PhoneSubtleColor}"/>
<SolidColorBrush x:Key="PhoneContrastBackgroundBrush" Color="{StaticResource PhoneContrastBackgroundColor}"/>
<SolidColorBrush x:Key="PhoneTextBoxBrush" Color="{StaticResource PhoneTextBoxColor}"/>
<SolidColorBrush x:Key="PhoneBorderBrush" Color="{StaticResource PhoneBorderColor}"/>
<SolidColorBrush x:Key="PhoneTextSelectionBrush" Color="{StaticResource PhoneTextSelectionColor}"/>
<SolidColorBrush x:Key="TransparentBrush" Color="Transparent"/>
<!-- Touch Target Area -->
<Thickness x:Key="PhoneTouchTargetOverhang">12</Thickness>
<!-- Default Border Size-->
<Thickness x:Key="PhoneDefaultBorderThickness">3</Thickness>
<!-- Font Names -->
<FontFamily x:Key="PhoneFontFamilyNormal">Segoe WP</FontFamily>
<FontFamily x:Key="PhoneFontFamilyLight">Segoe WP Light</FontFamily>
<FontFamily x:Key="PhoneFontFamilySemiLight">Segoe WP Semilight</FontFamily>
<FontFamily x:Key="PhoneFontFamilySemiBold">Segoe WP Semibold</FontFamily>
<!-- Font sizes -->
<!--14pt-->
<system:Double x:Key="PhoneFontSizeSmall">18.667</system:Double>
<!--15pt-->
<system:Double x:Key="PhoneFontSizeNormal">20</system:Double>
<!--17pt-->
<system:Double x:Key="PhoneFontSizeMedium">22.667</system:Double>
<!--19pt-->
<system:Double x:Key="PhoneFontSizeMediumLarge">25.333</system:Double>
<!--24pt-->
<system:Double x:Key="PhoneFontSizeLarge">32</system:Double>
<!--32pt-->
<system:Double x:Key="PhoneFontSizeExtraLarge">42.667</system:Double>
<!--54pt-->
<system:Double x:Key="PhoneFontSizeExtraExtraLarge">72</system:Double>
<!-- TextBox styles -->
<Style x:Key="PhoneTextBoxStyle" TargetType="TextBox">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeSmall}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneTextBoxBrush}"/>
</Style>
<!-- TextBlock styles -->
<Style x:Key="PhoneTextNormalStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextPageTitle1Style" TargetType="TextBlock" BasedOn="{StaticResource PhoneTextNormalStyle}">
<Setter Property="Margin" Value="20,20,0,0" />
</Style>
<Style x:Key="PhoneTextSubtleStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneSubtleBrush}"/>
</Style>
<Style x:Key="PhoneTextTitle1Style" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeExtraExtraLarge}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextPageTitle2Style" TargetType="TextBlock" BasedOn="{StaticResource PhoneTextTitle1Style}">
<Setter Property="Margin" Value="20,43,0,0" />
</Style>
<Style x:Key="PhoneTextTitle2Style" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeLarge}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextTitle3Style" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextExtraLargeStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeExtraLarge}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextGroupHeaderStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeLarge}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneSubtleBrush}"/>
</Style>
<Style x:Key="PhoneTextLargeStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiLight}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeLarge}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextSmallStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeSmall}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneSubtleBrush}"/>
</Style>
<Style x:Key="PhoneTextContrastStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneContrastForegroundBrush}"/>
</Style>
<Style x:Key="PhoneTextAccentStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeNormal}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
</Style>
<Style x:Key="PhoneTextBodyTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="LineHeight" Value="32"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Margin" Value="20,20,20,0" />
</Style>
<!--************ THEME RESOURCES ************-->
<!--***** LISTBOX/LISTBOXITEM TEMPLATES *****-->
<Style x:Key="PhoneListBox" TargetType="ListBox">
<Setter Property="Padding" Value="1"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Grid>
<ScrollViewer Foreground="{TemplateBinding Foreground}" x:Name="ScrollViewer" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Margin="7,1,1,1">
<ItemsPresenter/>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource TransparentBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Transparent"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" Duration="0" To=".55" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{StaticResource PhoneTouchTargetOverhang}">
<ContentPresenter x:Name="contentPresenter" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PhoneListBoxItemLayout" TargetType="mpc:ListViewItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="ImageStretch" Value="UniformToFill" />
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Height" Value="82"/>
<!-- The intended height of the control is 95 but the ItemsControl pads each element with 12 -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="mpc:ListViewItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}" Height="{TemplateBinding Height}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" x:Name="ItemText" Text="{TemplateBinding Text}" Style="{StaticResource PhoneTextExtraLargeStyle}" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" Margin="-3,-4,0,0"/>
<ContentPresenter Grid.Column="1" x:Name="SecondaryContent" Content="{TemplateBinding SecondaryContent}" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextWithIconTemplate">
<Setter.Value>
<ControlTemplate TargetType="mpc:ListViewItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="43"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{TemplateBinding ImageSource}" Stretch="{TemplateBinding ImageStretch}" Width="43" Height="43"/>
<TextBlock Grid.Column="1" Margin="9,-4,0,0" x:Name="ItemText" Text="{TemplateBinding Text}" Style="{StaticResource PhoneTextExtraLargeStyle}" VerticalAlignment="Center" />
<ContentPresenter Grid.Column="2" x:Name="SecondaryContent" Content="{TemplateBinding SecondaryContent}" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextAndDetailsTemplate">
<Setter.Value>
<ControlTemplate TargetType="mpc:ListViewItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Center" >
<TextBlock x:Name="ItemText" Text="{TemplateBinding Text}" Style="{StaticResource PhoneTextExtraLargeStyle}" HorizontalAlignment="Left" Margin="-3,-13,0,0" />
<TextBlock x:Name="DetailsText" Text="{TemplateBinding Details}" Style="{StaticResource PhoneTextSubtleStyle}" HorizontalAlignment="Left" Margin="-1,-6,0,0" />
</StackPanel>
<ContentPresenter Grid.Column="1" x:Name="SecondaryContent" Content="{TemplateBinding SecondaryContent}" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="TextAndDetailsWithIconTemplate">
<Setter.Value>
<ControlTemplate TargetType="mpc:ListViewItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="43"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{TemplateBinding ImageSource}" Stretch="{TemplateBinding ImageStretch}" Width="43" Height="43" VerticalAlignment="Top"/>
<StackPanel Grid.Column="1" Margin="12,0,0,0" VerticalAlignment="Center">
<TextBlock x:Name="ItemText" Text="{TemplateBinding Text}" Style="{StaticResource PhoneTextExtraLargeStyle}" HorizontalAlignment="Left" Margin="-3,-13,0,0"/>
<TextBlock x:Name="DetailsText" Text="{TemplateBinding Details}" Style="{StaticResource PhoneTextSubtleStyle}" HorizontalAlignment="Left" Margin="-1,-6,0,0" />
</StackPanel>
<ContentPresenter Grid.Column="2" x:Name="SecondaryContent" Content="{TemplateBinding SecondaryContent}" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="CustomTemplate">
<Setter.Value>
<ControlTemplate TargetType="mpc:ListViewItem">
<Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="12,0,0,0" x:Name="ItemText" Text="{TemplateBinding Text}" Style="{StaticResource PhoneTextExtraLargeStyle}" VerticalAlignment="Center" />
<ContentPresenter Grid.Column="1" x:Name="SecondaryContent" Content="{TemplateBinding SecondaryContent}" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--***** LISTBOX/LISTBOXITEM TEMPLATES *****-->
<!--************ BUTTON TEMPLATE ************-->
<Style x:Key="PhoneButtonBase" TargetType="ButtonBase">
<Setter Property="Background" Value="{StaticResource TransparentBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="MinHeight" Value="72" />
<Setter Property="BorderThickness" Value="{StaticResource PhoneDefaultBorderThickness}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Padding" Value="10,0,10,5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="foregroundContainer" Storyboard.TargetProperty="Control.Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Border.Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundColor}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Border.BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundColor}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="foregroundContainer" Storyboard.TargetProperty="Control.Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Control.BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ButtonBackground" Storyboard.TargetProperty="Control.Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" Background="{TemplateBinding Background}" Margin="{StaticResource PhoneTouchTargetOverhang}">
<ContentControl x:Name="foregroundContainer" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" FontSize="{TemplateBinding FontSize}" Padding="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--************ BUTTON TEMPLATE ************-->
<!--********* PHONE SLIDER TEMPLATE *********-->
<Style x:Key="PhoneSlider" TargetType="Slider">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Maximum" Value="10"/>
<Setter Property="Minimum" Value="0"/>
<Setter Property="MinHeight" Value="84"/>
<Setter Property="MinWidth" Value="60"/>
<Setter Property="Value" Value="0"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneAccentBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid x:Name="Root" Background="{TemplateBinding Background}">
<Grid.Resources>
<ControlTemplate x:Key="PhoneSimpleRepeatButton" TargetType="RepeatButton">
<Rectangle />
</ControlTemplate>
<ControlTemplate x:Key="PhoneSimpleThumb" TargetType="Thumb">
<Rectangle />
</ControlTemplate>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="HorizontalTrack" Storyboard.TargetProperty="Opacity" To="0.55" />
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="HorizontalThumbDisabledOverlay" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0" Storyboard.TargetName="VerticalTrack" Storyboard.TargetProperty="Opacity" To="0.55" />
<ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="VerticalThumbDisabledOverlay" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="HorizontalTemplate">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="0"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="HorizontalTrack" Fill="{StaticResource PhoneForegroundBrush}" Opacity="0.2" StrokeThickness="0" Grid.ColumnSpan="3" Margin="0,24,0,0" VerticalAlignment="Top" Height="12"/>
<Rectangle Fill="{TemplateBinding Foreground}" StrokeThickness="0" Grid.Column="0" Margin="0,24,0,0" VerticalAlignment="Top" Height="12"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeDecreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}" Background="Transparent"/>
<RepeatButton x:Name="HorizontalTrackLargeChangeIncreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}" Grid.Column="2" Background="Transparent"/>
<Thumb x:Name="HorizontalThumb" Width="1" Margin="-1,0,0,0" Grid.Column="1" BorderThickness="0" Template="{StaticResource PhoneSimpleThumb}" Background="Transparent" RenderTransformOrigin="0.5,0.5">
<Thumb.RenderTransform>
<ScaleTransform ScaleX="32" ScaleY="1"/>
</Thumb.RenderTransform>
</Thumb>
<Rectangle x:Name="HorizontalThumbDisabledOverlay" IsHitTestVisible="False" Opacity="0.55" Visibility="Collapsed" Fill="{StaticResource PhoneDisabledBrush}" Grid.Column="1" Height="12" Margin="0,24,0,0" VerticalAlignment="Top"/>
</Grid>
<Grid x:Name="VerticalTemplate">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="0"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Rectangle x:Name="VerticalTrack" Fill="{StaticResource PhoneForegroundBrush}" Opacity="0.2" StrokeThickness="0" HorizontalAlignment="Left" Margin="24,0,0,0" Width="12" Grid.RowSpan="3"/>
<Rectangle Fill="{TemplateBinding Foreground}" StrokeThickness="0" Grid.Row="2" HorizontalAlignment="Left" Margin="24,0,0,0" Width="12"/>
<RepeatButton x:Name="VerticalTrackLargeChangeDecreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}" Background="Transparent" Grid.Row="2"/>
<RepeatButton x:Name="VerticalTrackLargeChangeIncreaseRepeatButton" IsTabStop="False" Template="{StaticResource PhoneSimpleRepeatButton}" Grid.Row="2" Background="Transparent"/>
<Thumb x:Name="VerticalThumb" Width="{TemplateBinding Width}" Height="1" Margin="0,-1,0,0" IsTabStop="True" Grid.Row="1" BorderThickness="0" Template="{StaticResource PhoneSimpleThumb}" Background="Transparent" RenderTransformOrigin="0.5,0.5">
<Thumb.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="32"/>
</Thumb.RenderTransform>
</Thumb>
<Rectangle x:Name="VerticalThumbDisabledOverlay" HorizontalAlignment="Left" Margin="24,0,0,0" Width="12" IsHitTestVisible="False" Opacity="0.55" Visibility="Collapsed" Fill="{StaticResource PhoneDisabledBrush}" Grid.Row="1"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--********* PHONE SLIDER TEMPLATE *********-->
<!--****** PHONE TOGGLESWITCH TEMPLATE ******-->
<Style x:Key="PhoneToggleSwitch" TargetType="ToggleButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneBorderBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneBorderBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="MinWidth" Value="136"/>
<Setter Property="MaxWidth" Value="136"/>
<Setter Property="MinHeight" Value="96"/>
<Setter Property="MaxHeight" Value="96"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="border" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="borderDisabled" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked" >
<Storyboard>
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="switchButton" Storyboard.TargetProperty="(Canvas.Left)" To="80" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="rectangleSwitchOn" Storyboard.TargetProperty="Width" To="78" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="switchButtonDisabled" Storyboard.TargetProperty="(Canvas.Left)" To="80" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="rectangleSwitchOnDisabled" Storyboard.TargetProperty="Width" To="78" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="switchButton" Storyboard.TargetProperty="(Canvas.Left)" To="0" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="rectangleSwitchOn" Storyboard.TargetProperty="Width" To="0" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="switchButtonDisabled" Storyboard.TargetProperty="(Canvas.Left)" To="0" />
<DoubleAnimation Duration="00:00:00.3" Storyboard.TargetName="rectangleSwitchOnDisabled" Storyboard.TargetProperty="Width" To="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="border" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" Width="112" Height="32" HorizontalAlignment="Right" Margin="0,32,0,32" >
<Canvas x:Name="switchContainer" Margin="2">
<Rectangle x:Name="rectangleSwitchOn" Width="0" Height="24" Fill="{TemplateBinding Foreground}" />
<Grid x:Name="switchButton" Width="24" Height="24" Canvas.Left="0" Background="{StaticResource PhoneForegroundBrush}" >
<Rectangle Fill="{StaticResource PhoneBackgroundBrush}" Width="2" HorizontalAlignment="Left" StrokeThickness="0" Margin="5,4,0,4" />
<Rectangle Fill="{StaticResource PhoneBackgroundBrush}" Width="2" HorizontalAlignment="Center" StrokeThickness="0" Margin="0,4,0,4" />
<Rectangle Fill="{StaticResource PhoneBackgroundBrush}" Width="2" HorizontalAlignment="Right" StrokeThickness="0" Margin="0,4,5,4" />
</Grid>
</Canvas>
</Border>
<Border x:Name="borderDisabled" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" BorderBrush="{StaticResource PhoneInactiveBrush}" Width="112" Height="32" HorizontalAlignment="Right" Margin="0,32,0,32" Visibility="Collapsed" >
<Canvas x:Name="switchContainerDisabled" Margin="2">
<Rectangle x:Name="rectangleSwitchOnDisabled" Width="0" Height="24" Fill="{StaticResource PhoneInactiveBrush}" />
<Grid x:Name="switchButtonDisabled" Width="24" Height="24" Canvas.Left="0" Background="{StaticResource PhoneInactiveBrush}" />
</Canvas>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--****** PHONE TOGGLESWITCH TEMPLATE ******-->
</Application.Resources>
</jl:ApplicationBase>
<Application.ApplicationLifetimeObjects>
<shell:PhoneApplicationService />
</Application.ApplicationLifetimeObjects>
</jl:ApplicationBase>

View File

@ -8,6 +8,7 @@ namespace Jellyfish.Virtu
base("Virtu")
{
InitializeComponent();
InitializePhoneApplication();
}
}
}

View File

@ -1,33 +1,32 @@
<phoneNavigation:PhoneApplicationPage
<phone:PhoneApplicationPage
x:Class="Jellyfish.Virtu.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="480"
FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Title="Virtu">
<!--<tk:DockPanel Background="Black">-->
<Grid Background="{StaticResource PhoneBackgroundBrush}">
<!--<StackPanel Orientation="Horizontal" tk:DockPanel.Dock="Top">-->
<StackPanel Orientation="Horizontal">
<!--<Button x:Name="_disk1Button" Content="Disk 1" IsTabStop="False" Margin="4 4 0 4" MaxHeight="60"/>
<Button x:Name="_disk2Button" Content="Disk 2" IsTabStop="False" Margin="4 4 0 4" MaxHeight="60"/>-->
<jl:FrameRateCounter Margin="4 4 0 4" VerticalAlignment="Center"/>
</StackPanel>
<Grid>
<Image x:Name="_image" MinWidth="280" MinHeight="192"/>
<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"/>
Orientation="Landscape" SupportedOrientations="Landscape" Title="Virtu">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!--<StackPanel Orientation="Horizontal">
<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" />
</StackPanel>-->
<jl:FrameRateCounter Margin="0,0,4,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
<Grid Grid.Row="1">
<Image x:Name="_image" MinWidth="560" MinHeight="384" HorizontalAlignment="Center" VerticalAlignment="Center" />
<MediaElement x:Name="_media" />
<ScrollViewer x:Name="_debugScrollViewer" BorderThickness="0" IsTabStop="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debugText" FontFamily="Consolas" FontSize="12" Foreground="White" />
</ScrollViewer>
</Grid>
</Grid>
<!--</tk:DockPanel>-->
</phoneNavigation:PhoneApplicationPage>
</phone:PhoneApplicationPage>

View File

@ -1,6 +1,6 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Jellyfish.Virtu.Services;
using Microsoft.Phone.Controls;
@ -13,29 +13,35 @@ namespace Jellyfish.Virtu
{
InitializeComponent();
_storageService = new IsolatedStorageService(_machine);
_keyboardService = new SilverlightKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new SilverlightAudioService(_machine, this, _media);
_videoService = new SilverlightVideoService(_machine, this, _image);
if (!DesignerProperties.IsInDesignTool)
{
_debugService = new SilverlightDebugService(_machine, this);
_storageService = new IsolatedStorageService(_machine);
_keyboardService = new SilverlightKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new SilverlightAudioService(_machine, this, _media);
_videoService = new SilverlightVideoService(_machine, this, _image);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
_machine.Services.AddService(typeof(DebugService), _debugService);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
//_disk1Button.Click += (sender, e) => OnDiskButtonClick(0); // TODO
//_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
//_disk1Button.Click += (sender, e) => OnDiskButtonClick(0); // TODO
//_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
}
}
public void Dispose()
{
_machine.Dispose();
_debugService.Dispose();
_storageService.Dispose();
_keyboardService.Dispose();
_gamePortService.Dispose();
@ -43,6 +49,13 @@ namespace Jellyfish.Virtu
_videoService.Dispose();
}
public void WriteLine(string message)
{
_debugText.Text += message;
_debugScrollViewer.UpdateLayout();
_debugScrollViewer.ScrollToVerticalOffset(double.MaxValue);
}
private void OnCompositionTargetRendering(object sender, EventArgs e)
{
_keyboardService.Update();
@ -68,6 +81,7 @@ namespace Jellyfish.Virtu
private Machine _machine = new Machine();
private DebugService _debugService;
private StorageService _storageService;
private KeyboardService _keyboardService;
private GamePortService _gamePortService;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
<App xmlns="" ProductID="{89a50370-1ed9-4cf1-ad08-043b6e6f3c90}" Title="Virtu" RuntimeType="SilverLight" Version="1.0.0.0" Genre="NormalApp" Author="" Description="" Publisher="">
<App xmlns="" ProductID="{89a50370-1ed9-4cf1-ad08-043b6e6f3c90}" Title="Virtu" RuntimeType="Silverlight" Version="1.0.0.0" Genre="Apps.Normal" Author="Sean Fausett &amp; Nick Westgate" Description="Apple IIe Emulator" Publisher="Digital Jellyfish Design Ltd">
<IconPath IsRelative="true" IsResource="false">AppIcon.png</IconPath>
<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
@ -14,7 +14,7 @@
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
</Capabilities>
<Tasks>
<DefaultTask Name="_default" PlaceHolderString="Default task" />
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" />
</Tasks>
<Tokens>
<PrimaryToken TokenID="Jellyfish.Virtu.Silverlight.Phone.Token" TaskName="_default">

View File

@ -18,14 +18,13 @@ namespace Jellyfish.Virtu.Services
throw new ArgumentNullException("media");
}
_page = page;
_media = media;
_mediaSource = new WaveMediaStreamSource(SampleRate, SampleChannels, SampleBits, SampleSize, SampleLatency, OnMediaSourceUpdate);
_media.SetSource(_mediaSource);
_page.Loaded += (sender, e) => _media.Play();
page.Loaded += (sender, e) => _media.Play();
#if !WINDOWS_PHONE
_page.Unloaded += (sender, e) => _media.Stop();
page.Unloaded += (sender, e) => _media.Stop();
#endif
}
@ -54,7 +53,6 @@ namespace Jellyfish.Virtu.Services
Update(bufferSize, (source, count) => Buffer.BlockCopy(source, 0, buffer, 0, count));
}
private UserControl _page;
private MediaElement _media;
private WaveMediaStreamSource _mediaSource;
//private int _count;

View File

@ -1,4 +1,5 @@
using System;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
{
@ -15,18 +16,9 @@ namespace Jellyfish.Virtu.Services
_page = page;
}
public override void WriteLine(string message)
protected override void OnWriteLine(string message)
{
message = string.Concat(DateTime.Now, " ", message, Environment.NewLine);
if (_page.CheckAccess())
{
_page._debug.Text += message;
}
else
{
_page.Dispatcher.BeginInvoke(() => _page._debug.Text += message);
}
_page.Dispatcher.CheckBeginInvoke(() => _page.WriteLine(message + Environment.NewLine));
}
private MainPage _page;

View File

@ -17,11 +17,9 @@ namespace Jellyfish.Virtu.Services
throw new ArgumentNullException("page");
}
_page = page;
_page.KeyDown += OnPageKeyDown;
_page.KeyUp += OnPageKeyUp;
_page.LostFocus += OnPageLostFocus;
page.KeyDown += OnPageKeyDown;
page.KeyUp += OnPageKeyUp;
page.LostFocus += OnPageLostFocus;
}
public override bool IsKeyDown(int key)
@ -396,7 +394,6 @@ namespace Jellyfish.Virtu.Services
private static readonly int KeyCount = (int)(KeyValues.Max()) + 1;
private UserControl _page;
private bool[] _states = new bool[KeyCount];
private bool _capsLock;
private bool _updateAnyKeyDown;

View File

@ -27,21 +27,18 @@ namespace Jellyfish.Virtu.Services
_image = image;
_image.Source = _bitmap;
var content = Application.Current.Host.Content;
#if WINDOWS_PHONE
((Page)_page).OrientationChanged += (sender, e) => SetImageSize(swapOrientation: (e.Orientation & PageOrientation.Landscape) != 0);
#else
#if !WINDOWS_PHONE
_page.LayoutUpdated += (sender, e) => SetWindowSizeToContent();
content.FullScreenChanged += (sender, e) => SetImageSize();
#else
((PhoneApplicationPage)_page).OrientationChanged += (sender, e) => SetImageSize(swapOrientation: (e.Orientation & PageOrientation.Landscape) != 0);
#endif
content.Resized += (sender, e) => SetImageSize();
_page.SizeChanged += (sender, e) => SetImageSize();
}
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
_pixels[y * BitmapWidth + x] = (int)color;
_pixels[(y + 1) * BitmapWidth + x] = (_imageScale < 1) ? (int)color : 0x0;
_pixelsDirty = true;
}
@ -67,15 +64,10 @@ namespace Jellyfish.Virtu.Services
private void SetImageSize(bool swapOrientation = false)
{
var content = Application.Current.Host.Content;
_imageScale = swapOrientation ? Math.Min(content.ActualHeight / BitmapWidth, content.ActualWidth / BitmapHeight) :
Math.Min(content.ActualWidth / BitmapWidth, content.ActualHeight / BitmapHeight);
if (_imageScale > 1)
{
_imageScale = Math.Floor(_imageScale); // integer scale up
}
_image.Width = _imageScale * BitmapWidth;
_image.Height = _imageScale * BitmapHeight;
int uniformScale = Math.Max(1, swapOrientation ? Math.Min((int)_page.RenderSize.Height / BitmapWidth, (int)_page.RenderSize.Width / BitmapHeight) :
Math.Min((int)_page.RenderSize.Width / BitmapWidth, (int)_page.RenderSize.Height / BitmapHeight));
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
Machine.Video.DirtyScreen();
}
@ -98,7 +90,6 @@ namespace Jellyfish.Virtu.Services
private UserControl _page;
private Image _image;
private double _imageScale;
private WriteableBitmap _bitmap = new WriteableBitmap(BitmapWidth, BitmapHeight);
private int[] _pixels = new int[BitmapWidth * BitmapHeight];
private bool _pixelsDirty;

View File

@ -61,6 +61,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -69,6 +73,9 @@
<DependentUpon>MainApp.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>

23
Virtu/Wpf/MainPage.xaml Normal file
View File

@ -0,0 +1,23 @@
<UserControl x:Class="Jellyfish.Virtu.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library"
Focusable="True">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<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" />
</StackPanel>
<jl:FrameRateCounter Margin="0,0,4,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
<Grid Grid.Row="1">
<Image x:Name="_image" MinWidth="560" MinHeight="384" RenderOptions.BitmapScalingMode="NearestNeighbor" HorizontalAlignment="Center" VerticalAlignment="Center" />
<ScrollViewer x:Name="_debugScrollViewer" BorderThickness="0" Focusable="False" IsTabStop="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debugText" FontFamily="Consolas" FontSize="12" Foreground="White" />
</ScrollViewer>
</Grid>
</Grid>
</UserControl>

102
Virtu/Wpf/MainPage.xaml.cs Normal file
View File

@ -0,0 +1,102 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Jellyfish.Virtu.Services;
using Microsoft.Win32;
namespace Jellyfish.Virtu
{
public sealed partial class MainPage : UserControl, IDisposable
{
public MainPage()
{
InitializeComponent();
if (!DesignerProperties.GetIsInDesignMode(this))
{
_debugService = new WpfDebugService(_machine, this);
_storageService = new WpfStorageService(_machine);
_keyboardService = new WpfKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new WpfAudioService(_machine, this);
_videoService = new WpfVideoService(_machine, this, _image);
_machine.Services.AddService(typeof(DebugService), _debugService);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
_disk1Button.Click += (sender, e) => OnDiskButtonClick(0);
_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
}
}
public void Dispose()
{
_machine.Dispose();
_debugService.Dispose();
_storageService.Dispose();
_keyboardService.Dispose();
_gamePortService.Dispose();
_audioService.Dispose();
_videoService.Dispose();
}
public void WriteLine(string message)
{
_debugText.Text += message;
_debugScrollViewer.UpdateLayout();
_debugScrollViewer.ScrollToVerticalOffset(double.MaxValue);
}
private void OnCompositionTargetRendering(object sender, EventArgs e)
{
_keyboardService.Update();
_gamePortService.Update();
_videoService.Update();
}
private void OnDiskButtonClick(int drive)
{
var dialog = new OpenFileDialog() { Filter = "Disk Files (*.dsk;*.nib)|*.dsk;*.nib|All Files (*.*)|*.*" };
bool? result = dialog.ShowDialog();
if (result.HasValue && result.Value)
{
using (var stream = File.OpenRead(dialog.FileName))
{
_machine.Pause();
_machine.DiskII.Drives[drive].InsertDisk(dialog.FileName, stream, false);
var settings = _machine.Settings.DiskII;
if (drive == 0)
{
settings.Disk1.Name = dialog.FileName;
}
else
{
settings.Disk2.Name = dialog.FileName;
}
_machine.Unpause();
}
}
}
private Machine _machine = new Machine();
private DebugService _debugService;
private StorageService _storageService;
private KeyboardService _keyboardService;
private GamePortService _gamePortService;
private AudioService _audioService;
private VideoService _videoService;
}
}

View File

@ -1,19 +1,7 @@
<Window x:Class="Jellyfish.Virtu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:jl="clr-namespace:Jellyfish.Library;assembly=Jellyfish.Library"
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"/>
<jl:FrameRateCounter Margin="4 4 0 4" VerticalAlignment="Center"/>
</StackPanel>
<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>
xmlns:jv="clr-namespace:Jellyfish.Virtu"
Title="Virtu" WindowStartupLocation="CenterScreen" FocusManager.FocusedElement="{Binding ElementName=_mainPage}">
<jv:MainPage x:Name="_mainPage" />
</Window>

View File

@ -1,91 +1,12 @@
using System;
using System.IO;
using System.Windows;
using System.Windows.Media;
using Jellyfish.Virtu.Services;
using Jellyfish.Virtu.Settings;
using Microsoft.Win32;
using System.Windows;
namespace Jellyfish.Virtu
{
public sealed partial class MainWindow : Window, IDisposable
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
_debugService = new WpfDebugService(_machine, this);
_storageService = new WpfStorageService(_machine);
_keyboardService = new WpfKeyboardService(_machine, this);
_gamePortService = new GamePortService(_machine); // not connected
_audioService = new WpfAudioService(_machine, this);
_videoService = new WpfVideoService(_machine, this, _image);
_machine.Services.AddService(typeof(DebugService), _debugService);
_machine.Services.AddService(typeof(StorageService), _storageService);
_machine.Services.AddService(typeof(KeyboardService), _keyboardService);
_machine.Services.AddService(typeof(GamePortService), _gamePortService);
_machine.Services.AddService(typeof(AudioService), _audioService);
_machine.Services.AddService(typeof(VideoService), _videoService);
Loaded += (sender, e) => _machine.Start();
CompositionTarget.Rendering += OnCompositionTargetRendering;
Application.Current.Exit += (sender, e) => _machine.Stop();
_disk1Button.Click += (sender, e) => OnDiskButtonClick(0);
_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
}
public void Dispose()
{
_machine.Dispose();
_debugService.Dispose();
_storageService.Dispose();
_keyboardService.Dispose();
_gamePortService.Dispose();
_audioService.Dispose();
_videoService.Dispose();
}
private void OnCompositionTargetRendering(object sender, EventArgs e)
{
_keyboardService.Update();
_gamePortService.Update();
_videoService.Update();
}
private void OnDiskButtonClick(int drive)
{
var dialog = new OpenFileDialog() { Filter = "Disk Files (*.dsk;*.nib)|*.dsk;*.nib|All Files (*.*)|*.*" };
bool? result = dialog.ShowDialog();
if (result.HasValue && result.Value)
{
using (var stream = File.OpenRead(dialog.FileName))
{
_machine.Pause();
_machine.DiskII.Drives[drive].InsertDisk(dialog.FileName, stream, false);
var settings = _machine.Settings.DiskII;
if (drive == 0)
{
settings.Disk1.Name = dialog.FileName;
}
else
{
settings.Disk2.Name = dialog.FileName;
}
_machine.Unpause();
}
}
}
private Machine _machine = new Machine();
private DebugService _debugService;
private StorageService _storageService;
private KeyboardService _keyboardService;
private GamePortService _gamePortService;
private AudioService _audioService;
private VideoService _videoService;
}
}

View File

@ -2,6 +2,7 @@
using System.Runtime.InteropServices;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
@ -9,19 +10,22 @@ namespace Jellyfish.Virtu.Services
public sealed class WpfAudioService : AudioService
{
[SecurityCritical]
public WpfAudioService(Machine machine, Window window) :
public WpfAudioService(Machine machine, UserControl page) :
base(machine)
{
if (window == null)
if (page == null)
{
throw new ArgumentNullException("window");
throw new ArgumentNullException("page");
}
_window = window;
_directSound = new DirectSound(SampleRate, SampleChannels, SampleBits, SampleSize, OnDirectSoundUpdate);
_window.SourceInitialized += (sender, e) => _directSound.Start(_window.GetHandle());
_window.Closed += (sender, e) => _directSound.Stop();
page.Loaded += (sender, e) =>
{
var window = Window.GetWindow(page);
_directSound.Start(window.GetHandle());
window.Closed += (_sender, _e) => _directSound.Stop();
};
}
public override void SetVolume(double volume) // machine thread
@ -49,7 +53,6 @@ namespace Jellyfish.Virtu.Services
Update(bufferSize, (source, count) => Marshal.Copy(source, 0, buffer, count));
}
private Window _window;
private DirectSound _directSound;
//private int _count;
}

View File

@ -1,34 +1,26 @@
using System;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services
{
public sealed class WpfDebugService : DebugService
{
public WpfDebugService(Machine machine, MainWindow window) :
public WpfDebugService(Machine machine, MainPage page) :
base(machine)
{
if (window == null)
if (page == null)
{
throw new ArgumentNullException("window");
throw new ArgumentNullException("page");
}
_window = window;
_page = page;
}
public override void WriteLine(string message)
protected override void OnWriteLine(string message)
{
message = string.Concat(DateTime.Now, " ", message, Environment.NewLine);
if (_window.CheckAccess())
{
_window._debug.Text += message;
}
else
{
_window.Dispatcher.BeginInvoke(new Action(() => _window._debug.Text += message));
}
_page.Dispatcher.CheckInvoke(() => _page.WriteLine(message + Environment.NewLine));
}
private MainWindow _window;
private MainPage _page;
}
}

View File

@ -1,26 +1,24 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Jellyfish.Virtu.Services
{
public sealed class WpfKeyboardService : KeyboardService
{
public WpfKeyboardService(Machine machine, Window window) :
public WpfKeyboardService(Machine machine, UserControl page) :
base(machine)
{
if (window == null)
if (page == null)
{
throw new ArgumentNullException("window");
throw new ArgumentNullException("page");
}
_window = window;
_window.KeyDown += OnWindowKeyDown;
_window.KeyUp += OnWindowKeyUp;
_window.GotKeyboardFocus += (sender, e) => _updateAnyKeyDown = true;
page.KeyDown += OnPageKeyDown;
page.KeyUp += OnPageKeyUp;
page.GotKeyboardFocus += (sender, e) => _updateAnyKeyDown = true;
}
public override bool IsKeyDown(int key)
@ -60,9 +58,9 @@ namespace Jellyfish.Virtu.Services
return _states[(int)key];
}
private void OnWindowKeyDown(object sender, KeyEventArgs e)
private void OnPageKeyDown(object sender, KeyEventArgs e)
{
//DebugService.WriteLine(string.Concat("OnWindowKeyDn: Key=", e.Key));
//DebugService.WriteLine(string.Concat("OnPageKeyDn: Key=", e.Key));
_states[(int)((e.Key == Key.System) ? e.SystemKey : e.Key)] = true;
_updateAnyKeyDown = false;
@ -78,9 +76,9 @@ namespace Jellyfish.Virtu.Services
Update();
}
private void OnWindowKeyUp(object sender, KeyEventArgs e)
private void OnPageKeyUp(object sender, KeyEventArgs e)
{
//DebugService.WriteLine(string.Concat("OnWindowKeyUp: Key=", e.Key));
//DebugService.WriteLine(string.Concat("OnPageKeyUp: Key=", e.Key));
_states[(int)((e.Key == Key.System) ? e.SystemKey : e.Key)] = false;
_updateAnyKeyDown = true;
@ -292,7 +290,6 @@ namespace Jellyfish.Virtu.Services
private static readonly int KeyCount = (int)(KeyValues.Max()) + 1;
private Window _window;
private bool[] _states = new bool[KeyCount];
private bool _updateAnyKeyDown;
}

View File

@ -1,36 +1,32 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
namespace Jellyfish.Virtu.Services
{
public sealed class WpfVideoService : VideoService
{
[SecurityCritical]
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public WpfVideoService(Machine machine, Window window, Image image) :
public WpfVideoService(Machine machine, UserControl page, Image image) :
base(machine)
{
if (window == null)
if (page == null)
{
throw new ArgumentNullException("window");
throw new ArgumentNullException("page");
}
if (image == null)
{
throw new ArgumentNullException("image");
}
_window = window;
_page = page;
_image = image;
_image.Source = _bitmap;
_window.SizeChanged += (sender, e) => SetImageSize();
SystemEvents.DisplaySettingsChanged += (sender, e) => SetImageSize();
_page.Loaded += (sender, e) => SetWindowSizeToContent();
_page.SizeChanged += (sender, e) => SetImageSize();
}
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
@ -44,17 +40,18 @@ namespace Jellyfish.Virtu.Services
{
if (_isFullScreen != IsFullScreen)
{
var window = Window.GetWindow(_page);
if (IsFullScreen)
{
_window.SizeToContent = SizeToContent.Manual;
_window.WindowStyle = WindowStyle.None;
_window.WindowState = WindowState.Maximized;
window.ResizeMode = ResizeMode.NoResize;
window.WindowStyle = WindowStyle.None;
window.WindowState = WindowState.Maximized;
}
else
{
_window.WindowState = WindowState.Normal;
_window.WindowStyle = WindowStyle.SingleBorderWindow;
_window.SizeToContent = SizeToContent.WidthAndHeight;
window.WindowState = WindowState.Normal;
window.WindowStyle = WindowStyle.SingleBorderWindow;
window.ResizeMode = ResizeMode.CanResize;
}
_isFullScreen = IsFullScreen;
}
@ -68,13 +65,24 @@ namespace Jellyfish.Virtu.Services
private void SetImageSize()
{
int uniformScale = IsFullScreen ? Math.Min((int)SystemParameters.PrimaryScreenWidth / BitmapWidth, (int)SystemParameters.PrimaryScreenHeight / BitmapHeight) :
Math.Min((int)SystemParameters.FullPrimaryScreenWidth / BitmapWidth, (int)SystemParameters.FullPrimaryScreenHeight / BitmapHeight);
int uniformScale = Math.Max(1, Math.Min((int)_page.RenderSize.Width / BitmapWidth, (int)_page.RenderSize.Height / BitmapHeight));
_image.Width = uniformScale * BitmapWidth;
_image.Height = uniformScale * BitmapHeight;
Machine.Video.DirtyScreen();
}
private void SetWindowSizeToContent()
{
if (!_sizedToContent)
{
_sizedToContent = true;
var window = Application.Current.MainWindow;
var size = window.DesiredSize;
window.Width = size.Width;
window.Height = size.Height;
}
}
private const int BitmapWidth = 560;
private const int BitmapHeight = 384;
private const int BitmapDpi = 96;
@ -82,11 +90,12 @@ namespace Jellyfish.Virtu.Services
private static readonly int BitmapStride = (BitmapWidth * BitmapPixelFormat.BitsPerPixel + 7) / 8;
private static readonly Int32Rect BitmapRect = new Int32Rect(0, 0, BitmapWidth, BitmapHeight);
private Window _window;
private UserControl _page;
private Image _image;
private WriteableBitmap _bitmap = new WriteableBitmap(BitmapWidth, BitmapHeight, BitmapDpi, BitmapDpi, BitmapPixelFormat, null);
private uint[] _pixels = new uint[BitmapWidth * BitmapHeight];
private bool _pixelsDirty;
private bool _isFullScreen;
private bool _sizedToContent;
}
}

BIN
Virtu/Xna/Background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -18,10 +18,12 @@
<XnaOutputType>Game</XnaOutputType>
<XapFilename>$(AssemblyName).xap</XapFilename>
<SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate>
<XnaWindowsPhoneManifestTemplate>Properties\WindowsPhoneManifest.xml</XnaWindowsPhoneManifestTemplate>
<XnaWindowsPhoneManifestTemplate>Properties\WMAppManifest.xml</XnaWindowsPhoneManifestTemplate>
<ApplicationIcon>AppIcon.ico</ApplicationIcon>
<Thumbnail>AppThumbnail.png</Thumbnail>
<GameStartupType>Jellyfish.Virtu.MainGame</GameStartupType>
<TileImage>Background.png</TileImage>
<TileTitle>Virtu</TileTitle>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Windows Phone' ">
<DebugSymbols>true</DebugSymbols>
@ -189,14 +191,19 @@
<Compile Include="MainGame.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\AppManifest.xml">
<XnaPlatformSpecific>true</XnaPlatformSpecific>
</None>
<None Include="Properties\WMAppManifest.xml">
<XnaPlatformSpecific>true</XnaPlatformSpecific>
</None>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\AppManifest.xml" />
<Content Include="Properties\WindowsPhoneManifest.xml" />
<Content Include="AppIcon.ico" />
<Content Include="AppThumbnail.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Content Include="AppThumbnail.png" />
<Content Include="Background.png">
<XnaPlatformSpecific>true</XnaPlatformSpecific>
</Content>
</ItemGroup>
<ItemGroup>

View File

@ -63,9 +63,6 @@
<Reference Include="Microsoft.Xna.Framework.GamerServices">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Input.Touch">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Xact">
<Private>False</Private>
</Reference>
@ -202,9 +199,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="AppIcon.ico" />
<Content Include="AppThumbnail.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="AppThumbnail.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\Properties\Strings.resx">

View File

@ -63,9 +63,6 @@
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Input.Touch, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Xact, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">
<Private>False</Private>
</Reference>
@ -203,9 +200,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="AppIcon.ico" />
<Content Include="AppThumbnail.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="AppThumbnail.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\Properties\Strings.resx">

View File

@ -10,13 +10,9 @@ namespace Jellyfish.Virtu
public MainGame() :
base("Virtu")
{
#if WINDOWS_PHONE
GraphicsDeviceManager.IsFullScreen = true;
GraphicsDeviceManager.PreferredBackBufferWidth = 480; // TODO remove; works around known ctp issue
GraphicsDeviceManager.PreferredBackBufferHeight = 800;
#endif
#if WINDOWS
IsMouseVisible = true;
#endif
var frameRateCounter = new FrameRateCounter(this); // no initializers; avoids CA2000
Components.Add(frameRateCounter);
frameRateCounter.DrawOrder = 1;

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
<App xmlns="" ProductID="{89a50370-1ed9-4cf1-ad08-043b6e6f3c90}" Title="Virtu" RuntimeType="XNA" Version="1.0.0.0" Genre="Apps.Games" Author="Sean Fausett &amp; Nick Westgate" Description="Apple IIe Emulator" Publisher="Digital Jellyfish Design Ltd">
<IconPath IsRelative="true" IsResource="false">AppThumbnail.png</IconPath>
<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
<Capability Name="ID_CAP_LOCATION" />
<Capability Name="ID_CAP_SENSORS" />
<Capability Name="ID_CAP_MICROPHONE" />
<Capability Name="ID_CAP_MEDIALIB" />
<Capability Name="ID_CAP_GAMERSERVICES" />
<Capability Name="ID_CAP_PHONEDIALER" />
<Capability Name="ID_CAP_PUSH_NOTIFICATION" />
<Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
</Capabilities>
<Tasks>
<DefaultTask Name="_default" />
</Tasks>
<Tokens>
<PrimaryToken TokenID="Jellyfish.Virtu.Xna.Phone.Token" TaskName="_default">
<TemplateType5>
<BackgroundImageURI IsRelative="true" IsResource="false">AppThumbnail.png</BackgroundImageURI>
<Count>0</Count>
<Title>Virtu</Title>
</TemplateType5>
</PrimaryToken>
</Tokens>
</App>
</Deployment>

View File

@ -27,9 +27,9 @@ namespace Jellyfish.Virtu.Services
try
{
using (var storageContainer = _storageDevice.Value.OpenContainer(_game.Name))
using (var storageContainer = OpenContainer())
{
using (var stream = new FileStream(Path.Combine(storageContainer.Path, path), FileMode.Open, FileAccess.Read, FileShare.Read))
using (var stream = storageContainer.OpenFile(path))
{
reader(stream);
}
@ -47,15 +47,20 @@ namespace Jellyfish.Virtu.Services
throw new ArgumentNullException("writer");
}
using (var storageContainer = _storageDevice.Value.OpenContainer(_game.Name))
using (var storageContainer = OpenContainer())
{
using (var stream = new FileStream(Path.Combine(storageContainer.Path, path), FileMode.Create, FileAccess.Write, FileShare.None))
using (var stream = storageContainer.OpenFile(path))
{
writer(stream);
}
}
}
private StorageContainer OpenContainer()
{
return _storageDevice.Value.EndOpenContainer(_storageDevice.Value.BeginOpenContainer(_game.Name, null, null));
}
private GameBase _game;
private Lazy<StorageDevice> _storageDevice = new Lazy<StorageDevice>(() => StorageDevice.EndShowSelector(StorageDevice.BeginShowSelector(null, null)));
}

View File

@ -29,9 +29,7 @@ namespace Jellyfish.Virtu.Services
[SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow")]
public override void SetPixel(int x, int y, uint color)
{
uint rgbaColor = ((color << 16) & 0xFF0000) | (color & 0x00FF00) | ((color >> 16) & 0x0000FF); // convert from BGRA to RGBA
_pixels[y * TextureWidth + x] = rgbaColor;
_pixels[(y + 1) * TextureWidth + x] = (_textureScale < 1) ? rgbaColor : 0x0;
_pixels[y * TextureWidth + x] = (color & 0xFF00FF00) | ((color << 16) & 0x00FF0000) | ((color >> 16) & 0x000000FF); // RGBA
_pixelsDirty = true;
}
@ -74,36 +72,32 @@ namespace Jellyfish.Virtu.Services
bool portraitOrientation = (presentationParameters.DisplayOrientation & DisplayOrientation.Portrait) != 0;
if (portraitOrientation)
{
_textureScale = Math.Min((float)displayMode.TitleSafeArea.Width / TextureWidth, (float)displayMode.TitleSafeArea.Height / TextureHeight);
_textureScale = Math.Max(1, Math.Min(displayMode.TitleSafeArea.Width / TextureWidth, displayMode.TitleSafeArea.Height / TextureHeight));
presentationParameters.BackBufferWidth = displayMode.Width; // always use portrait display mode
presentationParameters.BackBufferHeight = displayMode.Height;
}
else
{
_textureScale = Math.Min((float)displayMode.TitleSafeArea.Height / TextureWidth, (float)displayMode.TitleSafeArea.Width / TextureHeight);
_textureScale = Math.Max(1, Math.Min(displayMode.TitleSafeArea.Height / TextureWidth, displayMode.TitleSafeArea.Width / TextureHeight));
presentationParameters.BackBufferWidth = displayMode.Height; // always use landscape display mode
presentationParameters.BackBufferHeight = displayMode.Width;
}
if (_textureScale > 1)
{
_textureScale = (float)Math.Floor(_textureScale); // integer scale up
}
#elif XBOX
_textureScale = Math.Min(displayMode.TitleSafeArea.Width / TextureWidth, displayMode.TitleSafeArea.Height / TextureHeight);
_textureScale = Math.Max(1, Math.Min(displayMode.TitleSafeArea.Width / TextureWidth, displayMode.TitleSafeArea.Height / TextureHeight));
presentationParameters.BackBufferWidth = displayMode.Width; // always use display mode
presentationParameters.BackBufferHeight = displayMode.Height;
#else
if (presentationParameters.IsFullScreen)
{
_textureScale = Math.Min((int)SystemParameters.PrimaryScreenWidth / TextureWidth, (int)SystemParameters.PrimaryScreenHeight / TextureHeight);
_textureScale = Math.Max(1, Math.Min((int)SystemParameters.PrimaryScreenWidth / TextureWidth, (int)SystemParameters.PrimaryScreenHeight / TextureHeight));
presentationParameters.BackBufferWidth = displayMode.Width; // avoids changing display mode
presentationParameters.BackBufferHeight = displayMode.Height;
}
else
{
_textureScale = Math.Min((int)SystemParameters.FullPrimaryScreenWidth / TextureWidth, (int)SystemParameters.FullPrimaryScreenHeight / TextureHeight);
presentationParameters.BackBufferWidth = (int)_textureScale * TextureWidth;
presentationParameters.BackBufferHeight = (int)_textureScale * TextureHeight;
_textureScale = Math.Max(1, Math.Min((int)SystemParameters.FullPrimaryScreenWidth / TextureWidth, (int)SystemParameters.FullPrimaryScreenHeight / TextureHeight));
presentationParameters.BackBufferWidth = _textureScale * TextureWidth;
presentationParameters.BackBufferHeight = _textureScale * TextureHeight;
}
#endif
}
@ -131,7 +125,7 @@ namespace Jellyfish.Virtu.Services
private SpriteBatch _spriteBatch;
private Texture2D _texture;
private Vector2 _texturePosition;
private float _textureScale;
private int _textureScale;
private uint[] _pixels;
private bool _pixelsDirty;
}