1pub mod bus;
2pub mod cartridge;
3pub mod consts;
4pub mod context;
5pub mod cpu;
6pub mod dsp;
7pub mod ppu;
8pub mod rom;
9pub mod spc;
10
11use crate::context::Context;
12pub use crate::rom::Rom;
13
14use meru_interface::EmulatorCore;
15use schemars::JsonSchema;
16use serde::{Deserialize, Serialize};
17use thiserror::Error;
18
19pub struct Snes {
20 pub ctx: Context,
21}
22
23impl Snes {
24 pub fn new(rom: Rom, backup: Option<&[u8]>) -> Self {
25 Self {
26 ctx: Context::from_rom(rom, backup),
27 }
28 }
29}
30
31#[derive(Default, JsonSchema, Serialize, Deserialize)]
32pub struct Config {}
33
34#[derive(Error, Debug)]
35pub enum Error {
36 #[error("{0}")]
37 RomError(#[from] rom::RomError),
38 #[error("deserialize failed: {0}")]
39 DeserializeFailed(#[from] bincode::Error),
40}
41
42const CORE_INFO: meru_interface::CoreInfo = meru_interface::CoreInfo {
43 system_name: "SNES (Super Sabicom)",
44 abbrev: "snes",
45 file_extensions: &["sfc", "smc", "swc", "fig"],
46};
47
48impl EmulatorCore for Snes {
49 type Config = Config;
50 type Error = Error;
51
52 fn core_info() -> &'static meru_interface::CoreInfo {
53 &CORE_INFO
54 }
55
56 fn try_from_file(
57 data: &[u8],
58 backup: Option<&[u8]>,
59 _config: &Self::Config,
60 ) -> Result<Self, Self::Error> {
61 Ok(Snes::new(rom::Rom::from_bytes(&data)?, backup))
62 }
63
64 fn game_info(&self) -> Vec<(String, String)> {
65 use context::Cartridge;
66 let rom = self.ctx.cartridge().rom();
67 let header = &rom.header;
68 let game_code = header.game_code.map_or_else(
69 || "N/A".to_string(),
70 |b| String::from_utf8_lossy(&b).to_string(),
71 );
72 vec![
73 ("Title".into(), header.title.clone()),
74 ("Game Code".into(), game_code),
75 ("Speed".into(), format!("{:?}", header.speed)),
76 ("Map Mode".into(), format!("{:?}", header.map_mode)),
77 ("Chipset".into(), format!("{}", header.chipset)),
78 ("ROM Size".into(), format!("{}", header.rom_size)),
79 ("File Size".into(), format!("{}", rom.rom.len())),
80 ("SRAM Size".into(), format!("{}", header.sram_size)),
81 ("Country".into(), format!("{}", header.country)),
82 ("Developer ID".into(), format!("{}", header.developer_id)),
83 ("Rom Version".into(), format!("{}", header.rom_version)),
84 ]
85 }
86
87 fn set_config(&mut self, _config: &Self::Config) {}
88
89 fn exec_frame(&mut self, render_graphics: bool) {
90 use context::*;
91
92 self.ctx.spc_mut().clear_audio_buffer();
93 self.ctx.ppu_mut().set_render_graphics(render_graphics);
94
95 let start_frame = self.ctx.ppu().frame();
96
97 while start_frame == self.ctx.ppu().frame() {
98 self.ctx.exec_one();
99 self.ctx.ppu_tick();
100 self.ctx.spc_tick();
101 self.ctx.bus_tick();
102 }
103 }
104
105 fn reset(&mut self) {
106 use context::Cartridge;
107
108 let rom = self.ctx.cartridge().rom().clone();
109 let backup = self.backup();
110
111 self.ctx = Context::from_rom(rom, backup.as_deref());
112 }
113
114 fn frame_buffer(&self) -> &meru_interface::FrameBuffer {
115 use context::Ppu;
116 self.ctx.ppu().frame_buffer()
117 }
118
119 fn audio_buffer(&self) -> &meru_interface::AudioBuffer {
120 use context::Spc;
121 self.ctx.spc().audio_buffer()
122 }
123
124 fn default_key_config() -> meru_interface::KeyConfig {
125 use meru_interface::key_assign::*;
126
127 let controller = vec![
128 ("A", any!(keycode!(X), pad_button!(0, East))),
129 ("B", any!(keycode!(Z), pad_button!(0, South))),
130 ("X", any!(keycode!(S), pad_button!(0, North))),
131 ("Y", any!(keycode!(A), pad_button!(0, West))),
132 ("L", any!(keycode!(Q), pad_button!(0, LeftTrigger))),
133 ("R", any!(keycode!(W), pad_button!(0, RightTrigger))),
134 ("Start", any!(keycode!(Return), pad_button!(0, Start))),
135 ("Select", any!(keycode!(LShift), pad_button!(0, Select))),
136 ("Up", any!(keycode!(Up), pad_button!(0, DPadUp))),
137 ("Down", any!(keycode!(Down), pad_button!(0, DPadDown))),
138 ("Left", any!(keycode!(Left), pad_button!(0, DPadLeft))),
139 ("Right", any!(keycode!(Right), pad_button!(0, DPadRight))),
140 ];
141
142 let empty = vec![
143 ("A", KeyAssign::default()),
144 ("B", KeyAssign::default()),
145 ("X", KeyAssign::default()),
146 ("Y", KeyAssign::default()),
147 ("L", KeyAssign::default()),
148 ("R", KeyAssign::default()),
149 ("Start", KeyAssign::default()),
150 ("Select", KeyAssign::default()),
151 ("Up", KeyAssign::default()),
152 ("Down", KeyAssign::default()),
153 ("Left", KeyAssign::default()),
154 ("Right", KeyAssign::default()),
155 ];
156
157 meru_interface::KeyConfig {
158 controllers: vec![controller, empty.clone(), empty.clone(), empty]
159 .into_iter()
160 .map(|kvs| {
161 kvs.into_iter()
162 .map(|(key, assign)| (key.to_string(), assign))
163 .collect()
164 })
165 .collect(),
166 }
167 }
168
169 fn set_input(&mut self, input: &meru_interface::InputData) {
170 use context::Bus;
171 self.ctx.bus_mut().set_input(input);
172 }
173
174 fn backup(&self) -> Option<Vec<u8>> {
175 use context::Cartridge;
176 self.ctx.cartridge().backup()
177 }
178
179 fn save_state(&self) -> Vec<u8> {
180 bincode::serialize(&self.ctx).unwrap()
181 }
182
183 fn load_state(&mut self, data: &[u8]) -> Result<(), Self::Error> {
184 use context::Cartridge;
185
186 let mut ctx: Context = bincode::deserialize(data)?;
187
188 ctx.cartridge_mut().restore(self.ctx.cartridge_mut());
190
191 self.ctx = ctx;
192
193 Ok(())
194 }
195}