diff --git a/.gitignore b/.gitignore
index 28494a9fb5755c7a9801f90b6bd09d1b75b4abae..b14114284023a6daab0d400ebd4b44ad96728f59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*.sv8
 *.rs.bk
 
 .DS_Store
diff --git a/examples/sdl/README.md b/examples/sdl/README.md
index 9c609b29211862e7cd4f3cb14f102b91452351cb..ee6856d5191dc0c995d30cfc175fad3e368f9d12 100644
--- a/examples/sdl/README.md
+++ b/examples/sdl/README.md
@@ -29,7 +29,7 @@ Drag and drop your ROM to play.
 * `T` Toggles the display of the diagnostics information
 * `O` Resets the machine
 * `P` Changes the pixel color of the system
-* `M` Takes a RAM and VRAM snapshot and saves it in `out.snp`
+* `M` Takes a RAM and VRAM snapshot and saves it in `.sv8`
 
 ## ROMs
 
diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs
index 82e523ef0f1ac9fe1a6b18284da54076b27a484f..fee2d737401c60acce335b379f0c85347576e504 100644
--- a/examples/sdl/src/main.rs
+++ b/examples/sdl/src/main.rs
@@ -1,6 +1,6 @@
 use chip_ahoyto::{
     chip8::Chip8, chip8_classic::Chip8Classic, chip8_classic::SCREEN_PIXEL_HEIGHT,
-    chip8_classic::SCREEN_PIXEL_WIDTH, chip8_neo::Chip8Neo, util::read_file,
+    chip8_classic::SCREEN_PIXEL_WIDTH, chip8_neo::Chip8Neo, util::read_file, util::save_snapshot,
 };
 use sdl2::{
     audio::AudioCallback, audio::AudioSpecDesired, event::Event, image::LoadSurface,
@@ -254,6 +254,16 @@ fn main() {
                     None
                 }
 
+                Event::KeyDown {
+                    keycode: Some(Keycode::M),
+                    ..
+                } => {
+                    if state.rom_loaded {
+                        save_snapshot(format!("{}.sv8", state.rom_name).as_str(), &state.system);
+                    }
+                    None
+                }
+
                 Event::KeyDown {
                     keycode: Some(Keycode::O),
                     ..
@@ -282,16 +292,31 @@ fn main() {
                 }
 
                 Event::DropFile { filename, .. } => {
-                    let rom = read_file(&filename);
-                    let rom_name = Path::new(&filename).file_name().unwrap().to_str().unwrap();
-
-                    state.system.reset_hard();
-                    state.system.load_rom(&rom);
-
-                    state.rom_name = String::from(rom_name);
-                    state.rom_loaded = true;
-
-                    state.set_title(&format!("{} [Currently playing: {}]", TITLE, rom_name));
+                    if filename.ends_with(".sv8") {
+                        let system_state = read_file(&filename);
+
+                        state.system.set_state(system_state.as_slice());
+
+                        state.rom_name = String::from(
+                            Path::new(&filename).file_stem().unwrap().to_str().unwrap(),
+                        );
+                        state.rom_loaded = true;
+                    } else {
+                        let rom = read_file(&filename);
+
+                        state.system.reset_hard();
+                        state.system.load_rom(&rom);
+
+                        state.rom_name = String::from(
+                            Path::new(&filename).file_name().unwrap().to_str().unwrap(),
+                        );
+                        state.rom_loaded = true;
+                    }
+
+                    state.set_title(&format!(
+                        "{} [Currently playing: {}]",
+                        TITLE, state.rom_name
+                    ));
 
                     None
                 }
diff --git a/src/chip8.rs b/src/chip8.rs
index 258e69cdde9d18c843666ca4b9e0098414b0c7a7..d805c3bff7171061bce37aff7222ba74bc70a65d 100644
--- a/src/chip8.rs
+++ b/src/chip8.rs
@@ -7,6 +7,8 @@ pub trait Chip8 {
     fn sp(&self) -> u8;
     fn ram(&self) -> Vec<u8>;
     fn vram(&self) -> Vec<u8>;
+    fn get_state(&self) -> Vec<u8>;
+    fn set_state(&mut self, state: &[u8]);
     fn load_rom(&mut self, rom: &[u8]);
     fn clock(&mut self);
     fn clock_dt(&mut self);
diff --git a/src/chip8_classic.rs b/src/chip8_classic.rs
index 383ba1fe03e4f630aed3b5901fd078c034eab9ef..66f0b6c21ebab04168db365f24068c55d86a4e8e 100644
--- a/src/chip8_classic.rs
+++ b/src/chip8_classic.rs
@@ -1,4 +1,4 @@
-use std::fmt::Display;
+use std::{fmt::Display, io::Cursor};
 
 use crate::{chip8::Chip8, util::random};
 
@@ -112,6 +112,12 @@ impl Chip8 for Chip8Classic {
         self.vram.to_vec()
     }
 
+    fn get_state(&self) -> Vec<u8> {
+        Vec::new()
+    }
+
+    fn set_state(&mut self, state: &[u8]) {}
+
     fn load_rom(&mut self, rom: &[u8]) {
         self.ram[ROM_START..ROM_START + rom.len()].clone_from_slice(rom);
     }
diff --git a/src/chip8_neo.rs b/src/chip8_neo.rs
index d661d5c70715dd15d5c23ed1aa71b4795c7f241b..9ec1a9a7e61fe165633a6d5b59e6f22c3070d6b7 100644
--- a/src/chip8_neo.rs
+++ b/src/chip8_neo.rs
@@ -1,3 +1,5 @@
+use std::io::{Cursor, Read};
+
 use crate::{chip8::Chip8, util::random};
 
 pub const DISPLAY_WIDTH: usize = 64;
@@ -243,6 +245,64 @@ impl Chip8 for Chip8Neo {
     fn vram(&self) -> Vec<u8> {
         self.vram.to_vec()
     }
+
+    fn get_state(&self) -> Vec<u8> {
+        let mut buffer: Vec<u8> = Vec::new();
+        buffer.extend(self.ram.iter());
+        buffer.extend(self.vram.iter());
+        buffer.extend(self.stack.map(|v| v.to_le_bytes()).iter().flatten());
+        buffer.extend(self.regs.iter());
+        buffer.extend(self.pc.to_le_bytes().iter());
+        buffer.extend(self.i.to_le_bytes().iter());
+        buffer.extend(self.sp.to_le_bytes().iter());
+        buffer.extend(self.dt.to_le_bytes().iter());
+        buffer.extend(self.st.to_le_bytes().iter());
+        buffer.extend(self.keys.map(|v| v as u8).iter());
+        buffer.extend(self.last_key.to_le_bytes().iter());
+        buffer
+    }
+
+    fn set_state(&mut self, state: &[u8]) {
+        let mut u8_buffer = [0u8; 1];
+        let mut u16_buffer = [0u8; 2];
+        let mut regs_buffer = [0u8; REGISTERS_SIZE * 2];
+        let mut keys_buffer = [0u8; KEYS_SIZE];
+
+        let mut cursor = Cursor::new(state.to_vec());
+
+        cursor.read_exact(&mut self.ram).unwrap();
+        cursor.read_exact(&mut self.vram).unwrap();
+        cursor.read_exact(&mut regs_buffer).unwrap();
+        self.stack.clone_from_slice(
+            regs_buffer
+                .chunks(2)
+                .map(|v| {
+                    u16_buffer.clone_from_slice(&v[0..2]);
+                    u16::from_le_bytes(u16_buffer)
+                })
+                .collect::<Vec<u16>>()
+                .as_slice(),
+        );
+        cursor.read_exact(&mut self.regs).unwrap();
+        cursor.read_exact(&mut u16_buffer).unwrap();
+        self.pc = u16::from_le_bytes(u16_buffer);
+        cursor.read_exact(&mut u16_buffer).unwrap();
+        self.i = u16::from_le_bytes(u16_buffer);
+        cursor.read_exact(&mut u8_buffer).unwrap();
+        self.sp = u8::from_le_bytes(u8_buffer);
+        cursor.read_exact(&mut u8_buffer).unwrap();
+        self.dt = u8::from_le_bytes(u8_buffer);
+        cursor.read_exact(&mut u8_buffer).unwrap();
+        self.st = u8::from_le_bytes(u8_buffer);
+        cursor.read_exact(&mut keys_buffer).unwrap();
+        self.keys.clone_from_slice(
+            keys_buffer
+                .map(|v| if v == 1 { true } else { false })
+                .as_slice(),
+        );
+        cursor.read_exact(&mut u8_buffer).unwrap();
+        self.last_key = u8::from_le_bytes(u8_buffer);
+    }
 }
 
 impl Chip8Neo {
diff --git a/src/util.rs b/src/util.rs
index 2af09704818966de7de929fa11daf495ff20607f..4563e6ee593e2aaaf111638406a8bb40fd8779af 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -22,9 +22,13 @@ pub fn random() -> u8 {
 
 /// Saves a snapshot image of the provided machine
 /// so that it can be latter loaded and RAM restored.
-pub fn save_snapshot(chip8: &Box<dyn Chip8>) {
-    let mut file = File::create("out.snp").unwrap();
-    file.write(&chip8.pc().to_le_bytes()).unwrap();
-    //file.write(&chip8.ram().tr().).unwrap();
-    //@todo need to serialize the rest of the machine
+pub fn save_snapshot(name: &str, chip8: &Box<dyn Chip8>) {
+    let mut file = File::create(name).unwrap();
+    let state = chip8.get_state();
+    let buffer = state.as_slice();
+    file.write(buffer).unwrap();
+}
+
+pub fn take_snapshot(chip8: &Box<dyn Chip8>) {
+    save_snapshot("out.sv8", chip8);
 }