use super::*; impl Ppu { pub fn save_state(&self, out: &mut Vec) { out.extend_from_slice(&self.vram); out.extend_from_slice(&self.palette_ram); out.extend_from_slice(&self.oam); out.push(self.ctrl); out.push(self.mask); out.push(self.status); out.push(self.oam_addr); out.push(u8::from(self.write_latch)); out.extend_from_slice(&self.vram_addr.to_le_bytes()); out.extend_from_slice(&self.temp_addr.to_le_bytes()); out.push(self.fine_x); out.push(self.scroll_x); out.push(self.scroll_y); out.push(self.read_buffer); out.push(self.io_latch); out.extend_from_slice(&self.bg_shift_pattern_lo.to_le_bytes()); out.extend_from_slice(&self.bg_shift_pattern_hi.to_le_bytes()); out.extend_from_slice(&self.bg_shift_attr_lo.to_le_bytes()); out.extend_from_slice(&self.bg_shift_attr_hi.to_le_bytes()); out.push(self.next_tile_id); out.push(self.next_tile_attr); out.push(self.next_tile_lsb); out.push(self.next_tile_msb); out.push(self.sprite_count); out.extend_from_slice(&self.sprite_indices); out.push(self.next_sprite_count); out.extend_from_slice(&self.next_sprite_indices); } pub fn load_state(&mut self, data: &[u8]) -> Result { let mut cursor = 0usize; self.vram.copy_from_slice(sio::take_exact( data, &mut cursor, VRAM_SIZE, PPU_STATE_CTX, )?); self.palette_ram.copy_from_slice(sio::take_exact( data, &mut cursor, PALETTE_SIZE, PPU_STATE_CTX, )?); self.oam .copy_from_slice(sio::take_exact(data, &mut cursor, OAM_SIZE, PPU_STATE_CTX)?); self.ctrl = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.mask = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.status = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.oam_addr = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.write_latch = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)? != 0; self.vram_addr = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)?; self.vram_addr &= 0x3FFF; self.temp_addr = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)? & 0x3FFF; self.fine_x = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.scroll_x = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.scroll_y = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.read_buffer = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.io_latch = if cursor < data.len() { sio::take_u8(data, &mut cursor, PPU_STATE_CTX)? } else { 0 }; if cursor + 30 <= data.len() { self.bg_shift_pattern_lo = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)?; self.bg_shift_pattern_hi = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)?; self.bg_shift_attr_lo = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)?; self.bg_shift_attr_hi = sio::take_u16(data, &mut cursor, PPU_STATE_CTX)?; self.next_tile_id = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.next_tile_attr = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.next_tile_lsb = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.next_tile_msb = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.sprite_count = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.sprite_indices.copy_from_slice(sio::take_exact( data, &mut cursor, 8, PPU_STATE_CTX, )?); self.next_sprite_count = sio::take_u8(data, &mut cursor, PPU_STATE_CTX)?; self.next_sprite_indices.copy_from_slice(sio::take_exact( data, &mut cursor, 8, PPU_STATE_CTX, )?); } else { self.bg_shift_pattern_lo = 0; self.bg_shift_pattern_hi = 0; self.bg_shift_attr_lo = 0; self.bg_shift_attr_hi = 0; self.next_tile_id = 0; self.next_tile_attr = 0; self.next_tile_lsb = 0; self.next_tile_msb = 0; self.sprite_count = 0; self.sprite_indices = [0; 8]; self.next_sprite_count = 0; self.next_sprite_indices = [0; 8]; } self.scroll_events.clear(); self.scroll_events.push(self.current_scroll_event(0, 0)); Ok(cursor) } }