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 @@ public ApplicationBase(string name)
//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 @@ private string GetExceptionCaption(string title, bool isTerminating = false)
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 @@ public ApplicationBase(string name)
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 @@ private string GetExceptionCaption(string title, bool isTerminating = false)
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 @@ public FrameRateCounter(GameBase game) :
{
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 @@ protected override void LoadContent()
Position = new Vector2(titleSafeArea.X, titleSafeArea.Y);
}
[SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
public override void Draw(GameTime gameTime)
{
_frameCount++;
@ -44,6 +40,7 @@ public override void Draw(GameTime gameTime)
_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 @@ public GameBase(string name)
{
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 @@ public Drive525()
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 @@ public void Start()
_storageService.Load(MachineSettings.FileName, stream => Settings.Deserialize(stream));
State = MachineState.Starting;
Services.ForEach(service => service.Start());
Thread.Start();
}
@ -68,15 +66,15 @@ public void Unpause()
public void Stop()
{
State = MachineState.Stopping;
Services.ForEach(service => service.Stop());
_pauseEvent.Set();
_unpauseEvent.Set();
Thread.Join();
Thread.IsAliveJoin();
State = MachineState.Stopped;
if (_storageService != null)
{
_storageService.Save(MachineSettings.FileName, stream => Settings.Serialize(stream));
}
}
private void Run() // machine thread
{

View File

@ -36,29 +36,33 @@ public MachineSettings()
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 @@ public void Output(int data) // machine thread
_readEvent.Set();
if (Machine.Settings.Cpu.IsThrottled)
{
_writeEvent.WaitOne();
_writeEvent.WaitOne(SampleLatency * 2); // allow timeout; avoids deadlock
}
}
}
@ -33,17 +34,11 @@ public void Reset()
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 @@ public DebugService(Machine machine) :
{
}
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 @@ public void Dispose()
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 @@ public void AddService(Type serviceType, MachineService serviceProvider)
_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

@ -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"/>
<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 BorderThickness="0" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debug" FontFamily="Consolas" FontSize="12" Foreground="White"/>
<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,6 +13,8 @@ public MainPage()
{
InitializeComponent();
if (!DesignerProperties.IsInDesignTool)
{
_debugService = new SilverlightDebugService(_machine, this);
_storageService = new IsolatedStorageService(_machine);
_keyboardService = new SilverlightKeyboardService(_machine, this);
@ -34,6 +36,7 @@ public MainPage()
_disk1Button.Click += (sender, e) => OnDiskButtonClick(0);
_disk2Button.Click += (sender, e) => OnDiskButtonClick(1);
}
}
public void Dispose()
{
@ -46,6 +49,13 @@ public void 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();

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: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>
<Application.ApplicationLifetimeObjects>
<shell:PhoneApplicationService />
</Application.ApplicationLifetimeObjects>
</jl:ApplicationBase>

View File

@ -8,6 +8,7 @@ public MainApp() :
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"/>
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 BorderThickness="0" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="_debug" FontFamily="Consolas" FontSize="12" Foreground="White"/>
<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,12 +13,16 @@ public MainPage()
{
InitializeComponent();
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);
@ -32,10 +36,12 @@ public MainPage()
//_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 @@ public void 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();
@ -68,6 +81,7 @@ private void OnCompositionTargetRendering(object sender, EventArgs e)
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 @@ public SilverlightAudioService(Machine machine, UserControl page, MediaElement m
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 @@ private void OnMediaSourceUpdate(byte[] buffer, int bufferSize) // audio thread
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 @@ public SilverlightDebugService(Machine machine, MainPage page) :
_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 @@ public SilverlightKeyboardService(Machine machine, UserControl page) :
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 @@ where field.IsLiteral
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 @@ public SilverlightVideoService(Machine machine, UserControl page, Image image) :
_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 @@ public override void Update() // main thread
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 @@ private void SetWindowSizeToContent()
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 @@ private void OnDirectSoundUpdate(IntPtr buffer, int bufferSize) // audio thread
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 @@ private bool IsKeyDown(Key key)
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 @@ private void OnWindowKeyDown(object sender, KeyEventArgs e)
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 @@ private static int GetAsciiKey(Key key, KeyboardDevice keyboard)
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 @@ public override void Update() // main thread
{
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 @@ public override void Update() // main thread
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 @@ private void SetImageSize()
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 @@ public sealed class MainGame : GameBase
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 @@ public override void Load(string path, Action<Stream> reader)
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 @@ public override void Save(string path, Action<Stream> writer)
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 @@ public XnaVideoService(Machine machine, GameBase game) :
[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 @@ private void OnGraphicsDeviceManagerPreparingDeviceSettings(object sender, Prepa
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 @@ private void SetTexturePosition()
private SpriteBatch _spriteBatch;
private Texture2D _texture;
private Vector2 _texturePosition;
private float _textureScale;
private int _textureScale;
private uint[] _pixels;
private bool _pixelsDirty;
}