From 365856485b16b6a6e86d3f8c91893c8c1cee7178 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sun, 6 Aug 2023 23:41:37 +0100
Subject: [PATCH] chore: initial tentative loading support

---
 src/cpu.rs   | 10 ++++++
 src/mmu.rs   | 12 +++++++
 src/state.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/src/cpu.rs b/src/cpu.rs
index 7d86859e..a05b7b89 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -482,6 +482,16 @@ impl Cpu {
         self.l = value as u8;
     }
 
+    #[inline(always)]
+    pub fn ime(&self) -> bool {
+        self.ime
+    }
+
+    #[inline(always)]
+    pub fn set_ime(&mut self, value: bool) {
+        self.ime = value;
+    }
+
     #[inline(always)]
     pub fn read_u8(&mut self) -> u8 {
         let byte = self.mmu.read(self.pc);
diff --git a/src/mmu.rs b/src/mmu.rs
index 7862f98f..a2f92b7a 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -507,6 +507,18 @@ impl Mmu {
         self.ram[addr as usize..addr as usize + buffer.len()].clone_from_slice(buffer);
     }
 
+    pub fn ram(&mut self) -> &mut Vec<u8> {
+        &mut self.ram
+    }
+
+    pub fn ram_i(&self) -> &Vec<u8> {
+        &self.ram
+    }
+
+    pub fn set_ram(&mut self, value: Vec<u8>) {
+        self.ram = value;
+    }
+
     pub fn rom(&mut self) -> &mut Cartridge {
         &mut self.rom
     }
diff --git a/src/state.rs b/src/state.rs
index de6e51b8..a46c0e86 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -48,6 +48,16 @@ impl BeesState {
             self.core.model,
         )
     }
+
+    pub fn verify(&self) -> Result<(), String> {
+        if let Err(result) = self.footer.verify() {
+            return Err(result);
+        }
+        if let Err(result) = self.core.verify() {
+            return Err(result);
+        }
+        Ok(())
+    }
 }
 
 impl Serialize for BeesState {
@@ -85,6 +95,7 @@ impl State for BeesState {
     }
 
     fn to_gb(&self, gb: &mut GameBoy) {
+        self.verify().unwrap();
         self.name.to_gb(gb);
         self.info.to_gb(gb);
         self.core.to_gb(gb);
@@ -127,6 +138,26 @@ impl Serialize for BeesBlockHeader {
 pub struct BeesBuffer {
     size: u32,
     offset: u32,
+    buffer: Vec<u8>,
+}
+
+impl BeesBuffer {
+    pub fn new(size: u32, offset: u32, buffer: Vec<u8>) -> Self {
+        Self {
+            size,
+            offset,
+            buffer,
+        }
+    }
+
+    fn load_buffer(&self, data: &mut Cursor<Vec<u8>>) -> Vec<u8> {
+        let mut buffer = vec![0x00; self.size as usize];
+        let position = data.position();
+        data.seek(SeekFrom::Start(self.offset as u64)).unwrap();
+        data.read_exact(&mut buffer).unwrap();
+        data.set_position(position);
+        buffer
+    }
 }
 
 impl Serialize for BeesBuffer {
@@ -142,6 +173,13 @@ impl Serialize for BeesBuffer {
         let mut buffer = [0x00; 4];
         data.read_exact(&mut buffer).unwrap();
         self.offset = u32::from_le_bytes(buffer);
+        self.buffer = self.load_buffer(data);
+    }
+}
+
+impl Default for BeesBuffer {
+    fn default() -> Self {
+        Self::new(0, 0, vec![])
     }
 }
 
@@ -157,6 +195,13 @@ impl BeesFooter {
             magic,
         }
     }
+
+    pub fn verify(&self) -> Result<(), String> {
+        if self.magic != 0x53534542 {
+            return Err(String::from("Invalid magic"));
+        }
+        Ok(())
+    }
 }
 
 impl Serialize for BeesFooter {
@@ -292,7 +337,7 @@ pub struct BeesCore {
     hl: u16,
     sp: u16,
 
-    ime: u8,
+    ime: bool,
     ie: u8,
     // 0 = running; 1 = halted; 2 = stopped
     execution_mode: u8,
@@ -330,19 +375,32 @@ impl BeesCore {
             de,
             hl,
             sp,
-            ime: 0,
+            ime: false,
             ie: 0,
             execution_mode: 0,
             _padding: 0,
             io_registers: [0x00; 128],
-            ram: BeesBuffer { size: 0, offset: 0 },
-            vram: BeesBuffer { size: 0, offset: 0 },
-            mbc_ram: BeesBuffer { size: 0, offset: 0 },
-            oam: BeesBuffer { size: 0, offset: 0 },
-            hram: BeesBuffer { size: 0, offset: 0 },
-            background_palettes: BeesBuffer { size: 0, offset: 0 },
-            object_palettes: BeesBuffer { size: 0, offset: 0 },
+            ram: BeesBuffer::default(),
+            vram: BeesBuffer::default(),
+            mbc_ram: BeesBuffer::default(),
+            oam: BeesBuffer::default(),
+            hram: BeesBuffer::default(),
+            background_palettes: BeesBuffer::default(),
+            object_palettes: BeesBuffer::default(),
+        }
+    }
+
+    pub fn verify(&self) -> Result<(), String> {
+        if self.header.magic != "CORE" {
+            return Err(String::from("Invalid magic"));
         }
+        if self.oam.size != 0xa0 {
+            return Err(String::from("Invalid OAM size"));
+        }
+        if self.hram.size != 0x7f {
+            return Err(String::from("Invalid HRAM size"));
+        }
+        Ok(())
     }
 }
 
@@ -386,7 +444,7 @@ impl Serialize for BeesCore {
 
         let mut buffer = [0x00; 1];
         data.read_exact(&mut buffer).unwrap();
-        self.ime = u8::from_le_bytes(buffer);
+        self.ime = buffer[0] != 0;
         let mut buffer = [0x00; 1];
         data.read_exact(&mut buffer).unwrap();
         self.ie = u8::from_le_bytes(buffer);
@@ -429,6 +487,19 @@ impl State for BeesCore {
         gb.cpu().set_de(self.de);
         gb.cpu().set_hl(self.hl);
         gb.cpu().set_sp(self.sp);
+
+        gb.cpu().set_ime(self.ime);
+        gb.mmu().ie = self.ie;
+
+        gb.mmu().write_many(0xff00, &self.io_registers);
+
+        gb.mmu().set_ram(self.ram.buffer.clone());
+        gb.mmu().write_many(0x8000, &self.vram.buffer);
+        //@TODO the MBC is missing
+        gb.mmu().write_many(0xfe00, &self.oam.buffer);
+        gb.mmu().write_many(0xff80, &self.hram.buffer);
+        //@TODO the background palettes are missing
+        //@TODO the object palettes are missing
     }
 }
 
@@ -468,6 +539,6 @@ pub fn load_state_file(file_path: &str, gb: &mut GameBoy) {
 pub fn load_state(data: &[u8], gb: &mut GameBoy) {
     let mut state = BeesState::default();
     state.load(&mut Cursor::new(data.to_vec()));
-    print!("{}", state);
     state.to_gb(gb);
+    print!("{}", state);
 }
-- 
GitLab