8:7
11pub const SMS_NTSC_ASPECT_RATIO: f64 = 1.1428571428571428;
11:8
14pub const SMS_PAL_ASPECT_RATIO: f64 = 1.375;
6:5
17pub const GAME_GEAR_LCD_ASPECT_RATIO: f64 = 1.2;
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode, EnumDisplay, EnumAll)] 20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 21#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))] 22pub enum SmsModel { 23 Sms1, 24 #[default] 25 Sms2, 26} 27 28#[derive( 29 Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode, EnumDisplay, EnumFromStr, EnumAll, 30)] 31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 32#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))] 33pub enum SmsGgRegion { 34 #[default] 35 International, 36 Domestic, 37} 38 39#[derive( 40 Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode, EnumDisplay, EnumFromStr, EnumAll, 41)] 42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 43#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))] 44pub enum SmsAspectRatio { 45 #[default] 46 Ntsc, 47 Pal, 48 SquarePixels, 49 Stretched, 50} 51 52impl SmsAspectRatio { 53 #[inline] 54 #[must_use] 55 pub fn to_pixel_aspect_ratio_f64(self) -> Option<f64> { 56 match self { 57 Self::Ntsc => Some(SMS_NTSC_ASPECT_RATIO), 58 Self::Pal => Some(SMS_PAL_ASPECT_RATIO), 59 Self::SquarePixels => Some(1.0), 60 Self::Stretched => None, 61 } 62 } 63 64 #[inline] 65 #[must_use] 66 #[allow(clippy::missing_panics_doc)] 67 pub fn to_pixel_aspect_ratio(self) -> Option<FiniteF64> { 68 self.to_pixel_aspect_ratio_f64().map(|par| FiniteF64::try_from(par).unwrap()) 69 } 70} 71 72#[derive( 73 Debug, Clone, Copy, PartialEq, Eq, Default, Encode, Decode, EnumDisplay, EnumFromStr, EnumAll, 74)] 75#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 76#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))] 77pub enum GgAspectRatio { 78 #[default] 79 GgLcd, 80 SquarePixels, 81 Stretched, 82} 83 84impl GgAspectRatio { 85 #[inline] 86 #[must_use] 87 pub fn to_pixel_aspect_ratio_f64(self) -> Option<f64> { 88 match self { 89 Self::GgLcd => Some(GAME_GEAR_LCD_ASPECT_RATIO), 90 Self::SquarePixels => Some(1.0), 91 Self::Stretched => None, 92 } 93 } 94 95 #[inline] 96 #[must_use] 97 #[allow(clippy::missing_panics_doc)] 98 pub fn to_pixel_aspect_ratio(self) -> Option<FiniteF64> { 99 self.to_pixel_aspect_ratio_f64().map(|par| FiniteF64::try_from(par).unwrap()) 100 } 101} 102 103define_controller_inputs! { 104 buttons: SmsGgButton { 105 Up -> up "Up", 106 Left -> left "Left", 107 Right -> right "Right", 108 Down -> down "Down", 109 Button1 -> button1 "Button 1", 110 Button2 -> button2 "Button 2", 111 }, 112 non_gamepad_buttons: [Pause "Start/Pause"], 113 joypad: SmsGgJoypadState impl with_allow_opposing_directions, 114 inputs: SmsGgInputs { 115 players: { 116 p1: Player::One, 117 p2: Player::Two, 118 }, 119 buttons: [Pause -> pause], 120 }, 121} 122 123#[cfg(test)] 124mod tests { 125 use super::*; 126 127 #[test] 128 fn all_sms_aspect_ratios_valid() { 129 for par in SmsAspectRatio::ALL { 130 let _ = par.to_pixel_aspect_ratio(); 131 } 132 } 133 134 #[test] 135 fn all_gg_aspect_ratios_valid() { 136 for par in GgAspectRatio::ALL { 137 let _ = par.to_pixel_aspect_ratio(); 138 } 139 } 140}