lib.rsannotatedlib.rssource140 lines · 3.7 KB · raw
1pub mod cheats;
2
3use bincode::{Decode, Encode};
4use jgenesis_common::define_controller_inputs;
5use jgenesis_common::frontend::FiniteF64;
6use jgenesis_proc_macros::{EnumAll, EnumDisplay, EnumFromStr};
7
8pub const NATIVE_Z80_DIVIDER: u32 = 15;

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}