diff --git a/Game1.cs b/Game1.cs
new file mode 100644
index 0000000..4044956
--- /dev/null
+++ b/Game1.cs
@@ -0,0 +1,134 @@
+#region Using Statements
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Storage;
+using Microsoft.Xna.Framework.GamerServices;
+using System.Diagnostics;
+#endregion
+
+namespace MonoGameSaveManager
+{
+ ///
+ /// A basic game to test out the SaveManager functionality.
+ /// Just follow along with the comments.
+ ///
+ public class Game1 : Game
+ {
+ GraphicsDeviceManager graphics;
+ SpriteBatch spriteBatch;
+
+ SaveManager save;
+ bool saved = false;
+
+ public Game1()
+ : base()
+ {
+ graphics = new GraphicsDeviceManager(this);
+ Content.RootDirectory = "Content";
+
+ string saveFolder = "SaveManagerTest"; // put your save folder name here
+ string saveFile = "test.sav"; // put your save file name here
+
+ // Pick one:
+
+ // - this will use the XNA StorageDevice method.
+ save = new StorageDeviceSaveManager(saveFolder, saveFile, PlayerIndex.One);
+
+ // - this will use the .NET IsolatedStorage method.
+ //save = new IsolatedStorageSaveManager(saveFolder, saveFile);
+ }
+
+ ///
+ /// Allows the game to perform any initialization it needs to before starting to run.
+ /// This is where it can query for any required services and load any non-graphic
+ /// related content. Calling base.Initialize will enumerate through any components
+ /// and initialize them as well.
+ ///
+ protected override void Initialize()
+ {
+ // TODO: Add your initialization logic here
+
+ base.Initialize();
+ }
+
+ ///
+ /// LoadContent will be called once per game and is the place to load
+ /// all of your content.
+ ///
+ protected override void LoadContent()
+ {
+ // Create a new SpriteBatch, which can be used to draw textures.
+ spriteBatch = new SpriteBatch(GraphicsDevice);
+
+ // TODO: use this.Content to load your game content here
+ }
+
+ ///
+ /// UnloadContent will be called once per game and is the place to unload
+ /// all content.
+ ///
+ protected override void UnloadContent()
+ {
+ // TODO: Unload any non ContentManager content here
+ }
+
+ ///
+ /// Allows the game to run logic such as updating the world,
+ /// checking for collisions, gathering input, and playing audio.
+ ///
+ /// Provides a snapshot of timing values.
+ protected override void Update(GameTime gameTime)
+ {
+ if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
+ Exit();
+
+ // test save stuff
+ // since this is Update, i don't want it to keep saving every tick
+ if (!saved)
+ {
+ saved = true;
+
+ // let's make up some save data
+ save.Data.testInt = 434;
+ save.Data.testBool = false;
+ save.Data.testString = "wow a test";
+
+ // save it
+ save.Save();
+
+ // erase data so we can check if loading works
+ save.Data = new SaveData();
+
+ // load it back
+ save.Load();
+
+ // did it work? let's hope so!
+ // this will show up in Visual Studio's Output window when running.
+ // you can also just use a Breakpoint or whatever.
+ Debug.WriteLine("final save data:");
+ Debug.WriteLine("testInt = " + save.Data.testInt);
+ Debug.WriteLine("testBool = " + save.Data.testBool);
+ Debug.WriteLine("testString = " + save.Data.testString);
+ }
+
+ base.Update(gameTime);
+ }
+
+ ///
+ /// This is called when the game should draw itself.
+ ///
+ /// Provides a snapshot of timing values.
+ protected override void Draw(GameTime gameTime)
+ {
+ GraphicsDevice.Clear(Color.CornflowerBlue);
+
+ // TODO: Add your drawing code here
+
+ base.Draw(gameTime);
+ }
+ }
+}
diff --git a/IsolatedStorageSaveManager.cs b/IsolatedStorageSaveManager.cs
new file mode 100644
index 0000000..0ee9943
--- /dev/null
+++ b/IsolatedStorageSaveManager.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.IsolatedStorage;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace MonoGameSaveManager
+{
+ ///
+ /// Uses the .NET IsolatedStorage to load/save game data.
+ /// Saves end up on "C:\Users\...\AppData\Local\IsolatedStorage\..." on Windows.
+ ///
+ public class IsolatedStorageSaveManager : SaveManager
+ {
+ ///
+ /// ///
+ /// Creates a new save game manager based on .NET IsolatedStorage.
+ ///
+ /// Name of the folder containing the save.
+ /// Name of the save file.
+ public IsolatedStorageSaveManager(string folderName, string fileName)
+ : base(folderName, fileName)
+ { }
+
+ public override void Load()
+ {
+ using (IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null))
+ {
+ // Ignore if directory doesn't exist.
+ if (!isf.DirectoryExists(folderName))
+ return;
+
+ string filePath = Path.Combine(folderName, fileName);
+
+ // Ignore if save doesn't exist.
+ if (!isf.FileExists(filePath))
+ return;
+
+ // Open the save file.
+ using (IsolatedStorageFileStream stream = isf.OpenFile(filePath, FileMode.Open))
+ {
+ // Get the XML data from the stream and convert it to object.
+ XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
+ Data = (SaveData)serializer.Deserialize(stream);
+ }
+ }
+ }
+
+ public override void Save()
+ {
+ using (IsolatedStorageFile isf = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Assembly, null, null))
+ {
+ // Create directory if it doesn't exist.
+ if (!isf.DirectoryExists(folderName))
+ isf.CreateDirectory(folderName);
+
+ string filePath = Path.Combine(folderName, fileName);
+
+ // Create new save file.
+ using (IsolatedStorageFileStream stream = isf.CreateFile(filePath))
+ {
+ // Convert the object to XML data and put it in the stream.
+ XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
+ serializer.Serialize(stream, Data);
+ }
+ }
+ }
+ }
+}
diff --git a/SaveData.cs b/SaveData.cs
new file mode 100644
index 0000000..32fe8da
--- /dev/null
+++ b/SaveData.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MonoGameSaveManager
+{
+ ///
+ /// Container for your save game data.
+ /// Put the variables you need here, as long as it's serializable.
+ ///
+ [Serializable]
+ public class SaveData
+ {
+ public int testInt;
+ public bool testBool;
+ public string testString;
+ }
+}
diff --git a/SaveManager.cs b/SaveManager.cs
new file mode 100644
index 0000000..5fbea59
--- /dev/null
+++ b/SaveManager.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MonoGameSaveManager
+{
+ ///
+ /// Manages a save file for you.
+ ///
+ public abstract class SaveManager
+ {
+ protected string folderName, fileName;
+
+ ///
+ /// Access save game data.
+ ///
+ public SaveData Data { get; set; }
+
+ ///
+ /// Creates a new save game manager.
+ ///
+ /// Name of the folder containing the save.
+ /// Name of the save file.
+ public SaveManager(string folderName, string fileName)
+ {
+ this.folderName = folderName;
+ this.fileName = fileName;
+ this.Data = new SaveData();
+ }
+
+ ///
+ /// Loads the data from disk to memory.
+ ///
+ public abstract void Load();
+
+ ///
+ /// Saves the data in memory to disk.
+ ///
+ public abstract void Save();
+ }
+}
diff --git a/StorageDeviceSaveManager.cs b/StorageDeviceSaveManager.cs
new file mode 100644
index 0000000..aab390a
--- /dev/null
+++ b/StorageDeviceSaveManager.cs
@@ -0,0 +1,100 @@
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Storage;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace MonoGameSaveManager
+{
+ ///
+ /// Uses the XNA StorageDevice to load/save game data.
+ /// Saves end up on "C:\Users\...\Documents\SavedGames\..." on Windows.
+ ///
+ public class StorageDeviceSaveManager : SaveManager
+ {
+ private PlayerIndex? player;
+
+ ///
+ /// Creates a new save game manager based on XNA StorageDevice.
+ ///
+ /// Name of the folder containing the save.
+ /// Name of the save file.
+ /// Player the save belongs to, or null for a global save.
+ public StorageDeviceSaveManager(string folderName, string fileName, PlayerIndex? player)
+ : base(folderName, fileName)
+ {
+ this.player = player;
+ }
+
+ private StorageDevice getStorageDevice()
+ {
+ IAsyncResult result;
+ // Get a global folder.
+ if (player == null)
+ result = StorageDevice.BeginShowSelector(null, null);
+ // Get a player-specific subfolder.
+ else
+ result = StorageDevice.BeginShowSelector((PlayerIndex)player, null, null);
+
+ result.AsyncWaitHandle.WaitOne();
+ StorageDevice device = StorageDevice.EndShowSelector(result);
+ result.AsyncWaitHandle.Close();
+ return device;
+ }
+
+ public override void Load()
+ {
+ // Open a storage device.
+ StorageDevice device = getStorageDevice();
+
+ // Open a storage container.
+ IAsyncResult result = device.BeginOpenContainer(folderName, null, null);
+ result.AsyncWaitHandle.WaitOne();
+ using (StorageContainer container = device.EndOpenContainer(result))
+ {
+ result.AsyncWaitHandle.Close();
+
+ // Ignore if save doesn't exist.
+ if (!container.FileExists(fileName))
+ return;
+
+ // Open the save file.
+ using (Stream stream = container.OpenFile(fileName, FileMode.Open))
+ {
+ // Get the XML data from the stream and convert it to object.
+ XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
+ Data = (SaveData)serializer.Deserialize(stream);
+ }
+ }
+ }
+
+ public override void Save()
+ {
+ // Open a storage device.
+ StorageDevice device = getStorageDevice();
+
+ // Open a storage container.
+ IAsyncResult resultStorage = device.BeginOpenContainer(folderName, null, null);
+ resultStorage.AsyncWaitHandle.WaitOne();
+ using (StorageContainer container = device.EndOpenContainer(resultStorage))
+ {
+ resultStorage.AsyncWaitHandle.Close();
+
+ // Delete old save file.
+ if (container.FileExists(fileName))
+ container.DeleteFile(fileName);
+
+ // Create new save file.
+ using (Stream stream = container.CreateFile(fileName))
+ {
+ // Convert the object to XML data and put it in the stream.
+ XmlSerializer serializer = new XmlSerializer(typeof(SaveData));
+ serializer.Serialize(stream, Data);
+ }
+ }
+ }
+ }
+}