Genesis memory map and 68000 + Z80 bus interfaces
9const MAIN_RAM_LEN_WORDS: usize = 64 * 1024 / 2; 10const AUDIO_RAM_LEN: usize = 8 * 1024; 11 12type RamCheatOverrides = CheatWordOverrides<0xFF0000, 0xFFFFFF>; 13 14#[derive(Debug, Clone, Encode, Decode)] 15pub struct Memory { 16 main_ram: BoxedWordArray<MAIN_RAM_LEN_WORDS>, 17 audio_ram: BoxedByteArray<AUDIO_RAM_LEN>, 18 ram_cheat_overrides: RamCheatOverrides, 19} 20 21impl Memory { 22 #[allow(clippy::missing_panics_doc)] 23 #[must_use] 24 pub fn new(config: &GenesisEmulatorConfig) -> Self { 25 Self { 26 main_ram: BoxedWordArray::new(), 27 audio_ram: BoxedByteArray::new(), 28 ram_cheat_overrides: RamCheatOverrides::new(&config.cheat_codes), 29 } 30 } 31 32 #[must_use] 33 pub fn read_main_ram_byte(&self, address: u32) -> u8 { 34 if let Some(cheat) = self.ram_cheat_overrides.get(address) { 35 return cheat.to_be_bytes()[(address & 1) as usize]; 36 } 37 38 let word = self.main_ram[((address & 0xFFFF) >> 1) as usize]; 39 word.to_be_bytes()[(address & 1) as usize] 40 } 41 42 #[must_use] 43 pub fn read_main_ram<const WORD: bool>(&self, address: u32) -> u16 { 44 if WORD { 45 self.read_main_ram_word(address) 46 } else { 47 self.read_main_ram_byte(address).into() 48 } 49 } 50 51 #[must_use] 52 pub fn read_main_ram_word(&self, address: u32) -> u16 { 53 if let Some(cheat) = self.ram_cheat_overrides.get(address) { 54 return cheat; 55 } 56 57 self.main_ram[((address & 0xFFFF) >> 1) as usize] 58 } 59 60 pub fn write_main_ram<const WORD: bool>(&mut self, address: u32, value: u16) { 61 if WORD { 62 self.write_main_ram_word(address, value); 63 } else { 64 self.write_main_ram_byte(address, value as u8); 65 } 66 } 67 68 pub fn write_main_ram_byte(&mut self, address: u32, value: u8) { 69 let word = &mut self.main_ram[((address & 0xFFFF) >> 1) as usize]; 70 if !address.bit(0) { 71 word.set_msb(value); 72 } else { 73 word.set_lsb(value); 74 } 75 } 76 77 pub fn write_main_ram_word(&mut self, address: u32, value: u16) { 78 self.main_ram[((address & 0xFFFF) >> 1) as usize] = value; 79 } 80 81 #[must_use] 82 pub fn read_audio_ram(&self, address: u16) -> u8 { 83 self.audio_ram[(address & 0x1FFF) as usize] 84 } 85 86 pub fn write_audio_ram(&mut self, address: u16, value: u8) { 87 self.audio_ram[(address & 0x1FFF) as usize] = value; 88 } 89 90 pub fn reload_config(&mut self, config: &GenesisEmulatorConfig) { 91 self.ram_cheat_overrides.update_cheat_codes(&config.cheat_codes); 92 } 93 94 #[must_use] 95 pub fn debug_ram_view(&mut self) -> (&mut [u16], &mut [u8]) { 96 (self.main_ram.as_mut_slice(), self.audio_ram.as_mut_slice()) 97 } 98}