Refactored XnaVideoService.

Redefined binary resources as EmbeddedResource type.
Miscellaneous cosmetic or otherwise minor changes.
This commit is contained in:
Sean Fausett 2012-04-14 16:46:32 +12:00
parent b0d09b7fb7
commit f16c1b0b90
34 changed files with 218 additions and 227 deletions

View File

@ -3,6 +3,8 @@
<Words> <Words>
<Recognized> <Recognized>
<Word>Alloc</Word> <Word>Alloc</Word>
<Word>x</Word>
<Word>y</Word>
</Recognized> </Recognized>
</Words> </Words>
</Dictionary> </Dictionary>

View File

@ -8,7 +8,7 @@
[assembly: AssemblyDescription("Common Library")] [assembly: AssemblyDescription("Common Library")]
[assembly: AssemblyProduct("Jellyfish.Library.Silverlight.Phone")] [assembly: AssemblyProduct("Jellyfish.Library.Silverlight.Phone")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")] [assembly: AssemblyComment("Developed by Sean Fausett")]
[assembly: AssemblyVersion("0.2.0.0")] [assembly: AssemblyVersion("0.2.0.0")]

View File

@ -8,7 +8,7 @@
[assembly: AssemblyDescription("Common Library")] [assembly: AssemblyDescription("Common Library")]
[assembly: AssemblyProduct("Jellyfish.Library.Silverlight")] [assembly: AssemblyProduct("Jellyfish.Library.Silverlight")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")] [assembly: AssemblyComment("Developed by Sean Fausett")]
[assembly: AssemblyVersion("0.2.0.0")] [assembly: AssemblyVersion("0.2.0.0")]

View File

@ -5,21 +5,22 @@ namespace Jellyfish.Library
{ {
public static class StreamExtensions public static class StreamExtensions
{ {
public static byte[] ReadAllBytes(this Stream stream) public static byte[] ReadBlock(this Stream stream, int count)
{ {
if (stream == null) return ReadBlock(stream, new byte[count], 0, count);
{
throw new ArgumentNullException("stream");
}
int count = (int)stream.Length;
byte[] buffer = new byte[count];
ReadBlock(stream, buffer, 0, count);
return buffer;
} }
public static int ReadBlock(this Stream stream, byte[] buffer, int offset, int count) public static byte[] ReadBlock(this Stream stream, byte[] buffer)
{
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
return ReadBlock(stream, buffer, 0, buffer.Length);
}
public static byte[] ReadBlock(this Stream stream, byte[] buffer, int offset, int count)
{ {
if (stream == null) if (stream == null)
{ {
@ -34,7 +35,38 @@ public static int ReadBlock(this Stream stream, byte[] buffer, int offset, int c
} }
while ((read > 0) && (total < count)); while ((read > 0) && (total < count));
return total; if (total < count)
{
throw new EndOfStreamException();
}
return buffer;
}
public static void SkipBlock(this Stream stream, int count)
{
if (stream == null)
{
throw new ArgumentNullException("stream");
}
if (stream.CanSeek)
{
stream.Seek(count, SeekOrigin.Current);
}
else
{
const int BufferSize = 1024;
byte[] buffer = new byte[BufferSize];
int total = 0;
int read;
do
{
total += read = stream.Read(buffer, 0, Math.Min(count - total, BufferSize));
}
while ((read > 0) && (total < count));
}
} }
} }
} }

View File

@ -8,7 +8,7 @@
[assembly: AssemblyDescription("Common Library")] [assembly: AssemblyDescription("Common Library")]
[assembly: AssemblyProduct("Jellyfish.Library.Wpf")] [assembly: AssemblyProduct("Jellyfish.Library.Wpf")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")] [assembly: AssemblyComment("Developed by Sean Fausett")]
[assembly: AssemblyVersion("0.2.0.0")] [assembly: AssemblyVersion("0.2.0.0")]

View File

@ -20,7 +20,7 @@ protected override void LoadContent()
_spriteBatch = new SpriteBatch(GraphicsDevice); _spriteBatch = new SpriteBatch(GraphicsDevice);
_spriteFont = Game.Content.Load<SpriteFont>(FontName); _spriteFont = Game.Content.Load<SpriteFont>(FontName);
var titleSafeArea = Game.GraphicsDevice.DisplayMode.TitleSafeArea; var titleSafeArea = Game.GraphicsDevice.Viewport.TitleSafeArea;
Position = new Vector2(titleSafeArea.X, titleSafeArea.Y); Position = new Vector2(titleSafeArea.X, titleSafeArea.Y);
} }

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Threading; using System.Threading;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
#if XBOX
using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.GamerServices;
#endif
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
@ -9,11 +11,6 @@ namespace Jellyfish.Library
{ {
public class GameBase : Game public class GameBase : Game
{ {
public GameBase() :
this(null)
{
}
public GameBase(string name) public GameBase(string name)
{ {
Name = name; Name = name;
@ -22,10 +19,12 @@ public GameBase(string name)
GraphicsDeviceManager = new GraphicsDeviceManager(this); GraphicsDeviceManager = new GraphicsDeviceManager(this);
#if WINDOWS_PHONE #if WINDOWS_PHONE
GraphicsDeviceManager.IsFullScreen = true; GraphicsDeviceManager.IsFullScreen = true;
GraphicsDeviceManager.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
TargetElapsedTime = TimeSpan.FromTicks(333333); // 30 fps TargetElapsedTime = TimeSpan.FromTicks(333333); // 30 fps
#elif XBOX #elif XBOX
GraphicsDeviceManager.IsFullScreen = true;
Components.Add(new GamerServicesComponent(this)); Components.Add(new GamerServicesComponent(this));
#else #elif WINDOWS
SynchronizationContext = new System.Windows.Forms.WindowsFormsSynchronizationContext(); SynchronizationContext = new System.Windows.Forms.WindowsFormsSynchronizationContext();
#endif #endif
GraphicsDeviceService = (IGraphicsDeviceService)Services.GetService(typeof(IGraphicsDeviceService)); GraphicsDeviceService = (IGraphicsDeviceService)Services.GetService(typeof(IGraphicsDeviceService));

View File

@ -14,7 +14,7 @@
[assembly: AssemblyProduct("Jellyfish.Library.Xna")] [assembly: AssemblyProduct("Jellyfish.Library.Xna")]
#endif #endif
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 2009-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 2009-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett")] [assembly: AssemblyComment("Developed by Sean Fausett")]
[assembly: AssemblyVersion("0.2.0.0")] [assembly: AssemblyVersion("0.2.0.0")]

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Input.Touch;
@ -6,6 +7,7 @@ namespace Jellyfish.Library
{ {
public sealed class TouchJoystick : TouchRegion public sealed class TouchJoystick : TouchRegion
{ {
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
public Vector2 GetJoystick() public Vector2 GetJoystick()
{ {
TouchLocation touch; TouchLocation touch;

View File

@ -1,4 +1,5 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework.Input.Touch; using Microsoft.Xna.Framework.Input.Touch;
namespace Jellyfish.Library namespace Jellyfish.Library
@ -9,6 +10,7 @@ public TouchRegionCollection()
{ {
} }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public void Update(ref TouchCollection touches) public void Update(ref TouchCollection touches)
{ {
for (int i = 0; i < base.Count; i++) for (int i = 0; i < base.Count; i++)

View File

@ -1,12 +1,12 @@
 GNU GENERAL PUBLIC LICENSE  GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble Preamble
The licenses for most software are designed to take away your The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public freedom to share and change it. By contrast, the GNU General Public
@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains 0. This License applies to any program or other work which contains
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. of promoting the sharing and reuse of software generally.
NO WARRANTY NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,63 +277,4 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using Jellyfish.Library;
namespace Jellyfish.Virtu namespace Jellyfish.Virtu
{ {
@ -13,25 +14,27 @@ protected Disk525(string name, byte[] data, bool isWriteProtected)
IsWriteProtected = isWriteProtected; IsWriteProtected = isWriteProtected;
} }
public static Disk525 CreateDisk(string name, byte[] data, bool isWriteProtected) public static Disk525 CreateDisk(string name, Stream stream, bool isWriteProtected)
{ {
if (name == null) if (name == null)
{ {
throw new ArgumentNullException("name"); throw new ArgumentNullException("name");
} }
if (data == null) if (stream == null)
{ {
throw new ArgumentNullException("data"); throw new ArgumentNullException("stream");
} }
if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase) && (data.Length == TrackCount * TrackSize)) if (name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase))
{
return new DiskNib(name, data, isWriteProtected);
}
else if (name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase) && (data.Length == TrackCount * SectorCount * SectorSize))
{ {
byte[] data = stream.ReadBlock(TrackCount * SectorCount * SectorSize);
return new DiskDsk(name, data, isWriteProtected); return new DiskDsk(name, data, isWriteProtected);
} }
else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase))
{
byte[] data = stream.ReadBlock(TrackCount * TrackSize);
return new DiskNib(name, data, isWriteProtected);
}
return null; return null;
} }
@ -48,7 +51,16 @@ public static Disk525 LoadState(BinaryReader reader, Version version)
bool isWriteProtected = reader.ReadBoolean(); bool isWriteProtected = reader.ReadBoolean();
byte[] data = reader.ReadBytes(reader.ReadInt32()); byte[] data = reader.ReadBytes(reader.ReadInt32());
return CreateDisk(name, data, isWriteProtected); if (name.EndsWith(".dsk", StringComparison.OrdinalIgnoreCase))
{
return new DiskDsk(name, data, isWriteProtected);
}
else if (name.EndsWith(".nib", StringComparison.OrdinalIgnoreCase))
{
return new DiskNib(name, data, isWriteProtected);
}
return null;
} }
public void SaveState(BinaryWriter writer) public void SaveState(BinaryWriter writer)

View File

@ -15,8 +15,8 @@ public DiskIIController(Machine machine) :
public override void Initialize() public override void Initialize()
{ {
StorageService.LoadResource("Roms/DiskII.rom", 0x0100, stream => stream.ReadBlock(_romRegionC1C7, 0, 0x0100)); StorageService.LoadResource("Roms/DiskII.rom", stream => stream.ReadBlock(_romRegionC1C7));
StorageService.LoadResource("Disks/Default.dsk", 0x23000, stream => _drives[0].InsertDisk("Default.dsk", stream, false)); StorageService.LoadResource("Disks/Default.dsk", stream => _drives[0].InsertDisk("Default.dsk", stream, false));
} }
public override void Reset() public override void Reset()

View File

@ -66,7 +66,7 @@ public void InsertDisk(string name, Stream stream, bool isWriteProtected)
// TODO handle null param/empty string for eject, or add Eject() // TODO handle null param/empty string for eject, or add Eject()
_disk = Disk525.CreateDisk(name, stream.ReadAllBytes(), isWriteProtected); _disk = Disk525.CreateDisk(name, stream, isWriteProtected);
_trackLoaded = false; _trackLoaded = false;
} }

View File

@ -50,7 +50,12 @@ public void Dispose()
public void Reset() public void Reset()
{ {
Components.ForEach(component => component.Reset()); foreach (var component in Components)
{
//_debugService.WriteLine("Resetting component '{0}'", component.GetType().Name);
component.Reset();
//_debugService.WriteLine("Reset component '{0}'", component.GetType().Name);
}
} }
public void Start() public void Start()
@ -99,14 +104,18 @@ public DiskIIController FindDiskIIController()
private void Initialize() private void Initialize()
{ {
Components.ForEach(component => component.Initialize()); foreach (var component in Components)
{
//_debugService.WriteLine("Initializing component '{0}'", component.GetType().Name);
component.Initialize();
//_debugService.WriteLine("Initialized component '{0}'", component.GetType().Name);
}
} }
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
private void LoadState() private void LoadState()
{ {
var storageService = Services.GetService<StorageService>(); _storageService.Load(Machine.LastStateFileName, stream =>
storageService.Load(Machine.LastStateFileName, stream =>
{ {
try try
{ {
@ -116,7 +125,12 @@ private void LoadState()
var stateVersion = new Version(reader.ReadString()); var stateVersion = new Version(reader.ReadString());
if ((stateSignature == StateSignature) && (stateVersion == new Version(Machine.Version))) // avoid state version mismatch (for now) if ((stateSignature == StateSignature) && (stateVersion == new Version(Machine.Version))) // avoid state version mismatch (for now)
{ {
Components.ForEach(component => component.LoadState(reader, stateVersion)); foreach (var component in Components)
{
//_debugService.WriteLine("Loading component '{0}' state", component.GetType().Name);
component.LoadState(reader, stateVersion);
//_debugService.WriteLine("Loaded component '{0}' state", component.GetType().Name);
}
} }
} }
} }
@ -132,25 +146,37 @@ private void LoadState()
private void Uninitialize() private void Uninitialize()
{ {
Components.ForEach(component => component.Uninitialize()); foreach (var component in Components)
{
//_debugService.WriteLine("Uninitializing component '{0}'", component.GetType().Name);
component.Uninitialize();
//_debugService.WriteLine("Uninitialized component '{0}'", component.GetType().Name);
}
} }
private void SaveState() private void SaveState()
{ {
var storageService = Services.GetService<StorageService>(); _storageService.Save(Machine.LastStateFileName, stream =>
storageService.Save(Machine.LastStateFileName, stream =>
{ {
using (var writer = new BinaryWriter(stream)) using (var writer = new BinaryWriter(stream))
{ {
writer.Write(StateSignature); writer.Write(StateSignature);
writer.Write(Machine.Version); writer.Write(Machine.Version);
Components.ForEach(component => component.SaveState(writer)); foreach (var component in Components)
{
//_debugService.WriteLine("Saving component '{0}' state", component.GetType().Name);
component.SaveState(writer);
//_debugService.WriteLine("Saved component '{0}' state", component.GetType().Name);
}
} }
}); });
} }
private void Run() // machine thread private void Run() // machine thread
{ {
_debugService = Services.GetService<DebugService>();
_storageService = Services.GetService<StorageService>();
Initialize(); Initialize();
Reset(); Reset();
LoadState(); LoadState();
@ -207,6 +233,9 @@ private void Run() // machine thread
private const string LastStateFileName = "LastState.bin"; private const string LastStateFileName = "LastState.bin";
private const string StateSignature = "Virtu"; private const string StateSignature = "Virtu";
private DebugService _debugService;
private StorageService _storageService;
private AutoResetEvent _pauseEvent = new AutoResetEvent(false); private AutoResetEvent _pauseEvent = new AutoResetEvent(false);
private AutoResetEvent _unpauseEvent = new AutoResetEvent(false); private AutoResetEvent _unpauseEvent = new AutoResetEvent(false);
} }

View File

@ -94,12 +94,12 @@ public override void Initialize()
_video = Machine.Video; _video = Machine.Video;
_noSlotClock = Machine.NoSlotClock; _noSlotClock = Machine.NoSlotClock;
StorageService.LoadResource("Roms/AppleIIe.rom", 0x4000, stream => StorageService.LoadResource("Roms/AppleIIe.rom", stream =>
{ {
stream.Seek(0x0100, SeekOrigin.Current); stream.SkipBlock(0x0100);
stream.ReadBlock(_romInternalRegionC1CF, 0, _romInternalRegionC1CF.Length); stream.ReadBlock(_romInternalRegionC1CF);
stream.ReadBlock(_romRegionD0DF, 0, _romRegionD0DF.Length); stream.ReadBlock(_romRegionD0DF);
stream.ReadBlock(_romRegionE0FF, 0, _romRegionE0FF.Length); stream.ReadBlock(_romRegionE0FF);
}); });
if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0xC1)) if ((ReadRomRegionE0FF(0xFBB3) == 0x06) && (ReadRomRegionE0FF(0xFBBF) == 0xC1))

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.1 // Runtime Version:4.0.30319.431
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
@ -60,15 +60,6 @@ internal Strings() {
} }
} }
/// <summary>
/// Looks up a localized string similar to Resource &apos;{0}&apos; invalid..
/// </summary>
internal static string ResourceInvalid {
get {
return ResourceManager.GetString("ResourceInvalid", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Resource &apos;{0}&apos; not found.. /// Looks up a localized string similar to Resource &apos;{0}&apos; not found..
/// </summary> /// </summary>

View File

@ -112,17 +112,14 @@
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="ResourceNotFound" xml:space="preserve"> <data name="ResourceNotFound" xml:space="preserve">
<value>Resource '{0}' not found.</value> <value>Resource '{0}' not found.</value>
</data> </data>
<data name="ResourceInvalid" xml:space="preserve">
<value>Resource '{0}' invalid.</value>
</data>
<data name="ServiceAlreadyPresent" xml:space="preserve"> <data name="ServiceAlreadyPresent" xml:space="preserve">
<value>Service type '{0}' already present.</value> <value>Service type '{0}' already present.</value>
</data> </data>

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
namespace Jellyfish.Virtu.Services namespace Jellyfish.Virtu.Services
{ {
@ -15,6 +16,11 @@ public void WriteLine(string message)
OnWriteLine(string.Concat(DateTime.Now.TimeOfDay, ' ', message)); OnWriteLine(string.Concat(DateTime.Now.TimeOfDay, ' ', message));
} }
public void WriteLine(string format, params object[] args)
{
WriteLine(string.Format(CultureInfo.InvariantCulture, format, args));
}
protected virtual void OnWriteLine(string message) protected virtual void OnWriteLine(string message)
{ {
Debug.WriteLine(message); Debug.WriteLine(message);

View File

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

View File

@ -1,4 +1,5 @@
using System; using System;
using Jellyfish.Library;
namespace Jellyfish.Virtu.Services namespace Jellyfish.Virtu.Services
{ {
@ -7,6 +8,8 @@ public abstract class MachineService : IDisposable
protected MachineService(Machine machine) protected MachineService(Machine machine)
{ {
Machine = machine; Machine = machine;
_debugService = new Lazy<DebugService>(() => Machine.Services.GetService<DebugService>());
} }
~MachineService() ~MachineService()
@ -25,6 +28,8 @@ protected virtual void Dispose(bool disposing)
} }
protected Machine Machine { get; private set; } protected Machine Machine { get; private set; }
protected DebugService DebugService { get { return Machine.Services.GetService<DebugService>(); } } protected DebugService DebugService { get { return _debugService.Value; } }
private Lazy<DebugService> _debugService;
} }
} }

View File

@ -65,7 +65,7 @@ public static void LoadFile(FileInfo fileInfo, Action<Stream> reader)
} }
} }
public static void LoadResource(string resourceName, int resourceSize, Action<Stream> reader) public static void LoadResource(string resourceName, Action<Stream> reader)
{ {
if (reader == null) if (reader == null)
{ {
@ -74,7 +74,7 @@ public static void LoadResource(string resourceName, int resourceSize, Action<St
try try
{ {
using (var stream = GetResourceStream(resourceName, resourceSize)) using (var stream = GetResourceStream(resourceName))
{ {
reader(stream); reader(stream);
} }
@ -122,21 +122,16 @@ public static void SaveFile(FileInfo fileInfo, Action<Stream> writer)
} }
} }
private static Stream GetResourceStream(string resourceName, int resourceSize) private static Stream GetResourceStream(string resourceName)
{ {
var resourceStream = _resourceManager.Value.GetStream(resourceName, CultureInfo.CurrentUICulture); resourceName = "Jellyfish.Virtu." + resourceName.Replace('/', '.');
var resourceStream = typeof(StorageService).Assembly.GetManifestResourceStream(resourceName);
if (resourceStream == null) if (resourceStream == null)
{ {
throw new FileNotFoundException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceNotFound, resourceName)); throw new FileNotFoundException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceNotFound, resourceName));
} }
if ((resourceSize > 0) && (resourceStream.Length != resourceSize))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Strings.ResourceInvalid, resourceName));
}
return resourceStream; return resourceStream;
} }
private static Lazy<ResourceManager> _resourceManager = new Lazy<ResourceManager>(() => new ResourceManager("Jellyfish.Virtu.g", typeof(StorageService).Assembly) { IgnoreCase = true });
} }
} }

View File

@ -230,15 +230,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\Disks\Default.dsk"> <EmbeddedResource Include="..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\DiskII.rom"> <EmbeddedResource Include="..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\CustomDictionary.xml">

View File

@ -228,15 +228,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\..\Disks\Default.dsk"> <EmbeddedResource Include="..\..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\..\Roms\DiskII.rom"> <EmbeddedResource Include="..\..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\..\CustomDictionary.xml">

View File

@ -9,7 +9,7 @@
[assembly: AssemblyDescription("Apple IIe Emulator")] [assembly: AssemblyDescription("Apple IIe Emulator")]
[assembly: AssemblyProduct("Jellyfish.Virtu.Silverlight.Phone")] [assembly: AssemblyProduct("Jellyfish.Virtu.Silverlight.Phone")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 1995-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")] [assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
[assembly: AssemblyVersion(Machine.Version)] [assembly: AssemblyVersion(Machine.Version)]

View File

@ -9,7 +9,7 @@
[assembly: AssemblyDescription("Apple IIe Emulator")] [assembly: AssemblyDescription("Apple IIe Emulator")]
[assembly: AssemblyProduct("Jellyfish.Virtu.Silverlight")] [assembly: AssemblyProduct("Jellyfish.Virtu.Silverlight")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 1995-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")] [assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
[assembly: AssemblyVersion(Machine.Version)] [assembly: AssemblyVersion(Machine.Version)]

View File

@ -219,15 +219,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\Disks\Default.dsk"> <EmbeddedResource Include="..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\DiskII.rom"> <EmbeddedResource Include="..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\CustomDictionary.xml">

View File

@ -10,7 +10,7 @@
[assembly: AssemblyDescription("Apple IIe Emulator")] [assembly: AssemblyDescription("Apple IIe Emulator")]
[assembly: AssemblyProduct("Jellyfish.Virtu.Wpf")] [assembly: AssemblyProduct("Jellyfish.Virtu.Wpf")]
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 1995-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")] [assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
[assembly: AssemblyVersion(Machine.Version)] [assembly: AssemblyVersion(Machine.Version)]

View File

@ -232,15 +232,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\Disks\Default.dsk"> <EmbeddedResource Include="..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\DiskII.rom"> <EmbeddedResource Include="..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\CustomDictionary.xml">

View File

@ -230,15 +230,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\Disks\Default.dsk"> <EmbeddedResource Include="..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\DiskII.rom"> <EmbeddedResource Include="..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\CustomDictionary.xml">

View File

@ -234,15 +234,15 @@
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="..\Disks\Default.dsk"> <EmbeddedResource Include="..\Disks\Default.dsk">
<Link>Disks\Default.dsk</Link> <Link>Disks\Default.dsk</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\AppleIIe.rom"> <EmbeddedResource Include="..\Roms\AppleIIe.rom">
<Link>Roms\AppleIIe.rom</Link> <Link>Roms\AppleIIe.rom</Link>
</Resource> </EmbeddedResource>
<Resource Include="..\Roms\DiskII.rom"> <EmbeddedResource Include="..\Roms\DiskII.rom">
<Link>Roms\DiskII.rom</Link> <Link>Roms\DiskII.rom</Link>
</Resource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CodeAnalysisDictionary Include="..\CustomDictionary.xml"> <CodeAnalysisDictionary Include="..\CustomDictionary.xml">

View File

@ -15,7 +15,7 @@
[assembly: AssemblyProduct("Jellyfish.Virtu.Xna")] [assembly: AssemblyProduct("Jellyfish.Virtu.Xna")]
#endif #endif
[assembly: AssemblyCompany("Digital Jellyfish Design Ltd")] [assembly: AssemblyCompany("Digital Jellyfish Design Ltd")]
[assembly: AssemblyCopyright("Copyright © 1995-2010 Digital Jellyfish Design Ltd")] [assembly: AssemblyCopyright("Copyright © 1995-2012 Digital Jellyfish Design Ltd")]
[assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")] [assembly: AssemblyComment("Developed by Sean Fausett & Nick Westgate")]
[assembly: AssemblyVersion(Machine.Version)] [assembly: AssemblyVersion(Machine.Version)]

View File

@ -86,7 +86,7 @@ private bool IsKeyDown(Keys key)
private void OnKeyDown(Keys key, bool gamePadControl) private void OnKeyDown(Keys key, bool gamePadControl)
{ {
//DebugService.WriteLine(string.Concat("OnKeyDn: Key=", key)); //DebugService.WriteLine("OnKeyDn: Key='{0}'", key);
int asciiKey = GetAsciiKey(key, gamePadControl); int asciiKey = GetAsciiKey(key, gamePadControl);
if (asciiKey >= 0) if (asciiKey >= 0)
@ -97,7 +97,7 @@ private void OnKeyDown(Keys key, bool gamePadControl)
private void OnKeyUp(Keys key, bool gamePadControl) private void OnKeyUp(Keys key, bool gamePadControl)
{ {
//DebugService.WriteLine(string.Concat("OnKeyUp: Key=", key)); //DebugService.WriteLine("OnKeyUp: Key='{0}'", key);
bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl); bool control = IsKeyDown(Keys.LeftControl) || IsKeyDown(Keys.RightControl);

View File

@ -20,10 +20,10 @@ public XnaVideoService(Machine machine, GameBase game) :
} }
_game = game; _game = game;
#if WINDOWS || XBOX
_game.GraphicsDeviceManager.PreparingDeviceSettings += OnGraphicsDeviceManagerPreparingDeviceSettings; _game.GraphicsDeviceManager.PreparingDeviceSettings += OnGraphicsDeviceManagerPreparingDeviceSettings;
#endif
_game.GraphicsDeviceService.DeviceCreated += OnGraphicsDeviceServiceDeviceCreated; _game.GraphicsDeviceService.DeviceCreated += OnGraphicsDeviceServiceDeviceCreated;
_game.GraphicsDeviceService.DeviceReset += (sender, e) => SetTexturePosition();
} }
public override void SetFullScreen(bool isFullScreen) public override void SetFullScreen(bool isFullScreen)
@ -53,8 +53,12 @@ public override void Update() // main thread
_texture.SetData(_pixels); _texture.SetData(_pixels);
} }
var viewport = _graphicsDevice.Viewport;
int scale = Math.Max(1, Math.Min(viewport.Width / TextureWidth, viewport.Height / TextureHeight));
var position = new Vector2((viewport.Width - scale * TextureWidth) / 2, (viewport.Height - scale * TextureHeight) / 2);
_spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, null, null); _spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Opaque, SamplerState.PointClamp, null, null);
_spriteBatch.Draw(_texture, _texturePosition, null, Color.White, 0, Vector2.Zero, _textureScale, SpriteEffects.None, 0); _spriteBatch.Draw(_texture, position, null, Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
_spriteBatch.End(); _spriteBatch.End();
} }
@ -69,58 +73,32 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing); base.Dispose(disposing);
} }
#if WINDOWS || XBOX
private void OnGraphicsDeviceManagerPreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) private void OnGraphicsDeviceManagerPreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
{ {
var displayMode = e.GraphicsDeviceInformation.Adapter.CurrentDisplayMode;
var presentationParameters = e.GraphicsDeviceInformation.PresentationParameters; var presentationParameters = e.GraphicsDeviceInformation.PresentationParameters;
#if WINDOWS
#if WINDOWS_PHONE if (!presentationParameters.IsFullScreen)
bool portraitOrientation = (presentationParameters.DisplayOrientation & DisplayOrientation.Portrait) != 0;
if (portraitOrientation)
{ {
_textureScale = Math.Max(1, Math.Min(displayMode.TitleSafeArea.Width / TextureWidth, displayMode.TitleSafeArea.Height / TextureHeight)); var maxScale = Math.Max(1, Math.Min((int)SystemParameters.FullPrimaryScreenWidth / TextureWidth, (int)SystemParameters.FullPrimaryScreenHeight / TextureHeight));
presentationParameters.BackBufferWidth = displayMode.Width; // always use portrait display mode presentationParameters.BackBufferWidth = maxScale * TextureWidth;
presentationParameters.BackBufferHeight = displayMode.Height; presentationParameters.BackBufferHeight = maxScale * TextureHeight;
} }
else else
{
_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;
}
#elif XBOX
_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.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.Max(1, Math.Min((int)SystemParameters.FullPrimaryScreenWidth / TextureWidth, (int)SystemParameters.FullPrimaryScreenHeight / TextureHeight));
presentationParameters.BackBufferWidth = _textureScale * TextureWidth;
presentationParameters.BackBufferHeight = _textureScale * TextureHeight;
}
#endif #endif
{
var displayMode = e.GraphicsDeviceInformation.Adapter.CurrentDisplayMode; // use display mode
presentationParameters.BackBufferWidth = displayMode.Width;
presentationParameters.BackBufferHeight = displayMode.Height;
}
} }
#endif
private void OnGraphicsDeviceServiceDeviceCreated(object sender, EventArgs e) private void OnGraphicsDeviceServiceDeviceCreated(object sender, EventArgs e)
{ {
_graphicsDevice = _game.GraphicsDevice; _graphicsDevice = _game.GraphicsDevice;
_spriteBatch = new SpriteBatch(_graphicsDevice); _spriteBatch = new SpriteBatch(_graphicsDevice);
_texture = new Texture2D(_graphicsDevice, TextureWidth, TextureHeight, false, SurfaceFormat.Color); _texture = new Texture2D(_graphicsDevice, TextureWidth, TextureHeight, false, SurfaceFormat.Color);
_pixels = new uint[TextureWidth * TextureHeight];
SetTexturePosition();
}
private void SetTexturePosition()
{
_texturePosition.X = (_graphicsDevice.PresentationParameters.BackBufferWidth - TextureWidth * _textureScale) / 2; // centered
_texturePosition.Y = (_graphicsDevice.PresentationParameters.BackBufferHeight - TextureHeight * _textureScale) / 2;
} }
private const int TextureWidth = 560; private const int TextureWidth = 560;
@ -130,9 +108,8 @@ private void SetTexturePosition()
private GraphicsDevice _graphicsDevice; private GraphicsDevice _graphicsDevice;
private SpriteBatch _spriteBatch; private SpriteBatch _spriteBatch;
private Texture2D _texture; private Texture2D _texture;
private Vector2 _texturePosition;
private int _textureScale; private uint[] _pixels = new uint[TextureWidth * TextureHeight];
private uint[] _pixels;
private bool _pixelsDirty; private bool _pixelsDirty;
} }
} }