1use crate::input::{GenericInput, Hotkey, KeyboardInput};
2use gb_config::GameBoyButton;
3use gba_config::GbaButton;
4use genesis_config::{GenesisButton, GenesisControllerType};
5use jgenesis_common::input::Player;
6use jgenesis_proc_macros::{ConfigDisplay, EnumAll, EnumDisplay};
7use nes_config::NesButton;
8use pce_config::PceButton;
9use sdl3::keyboard::Keycode;
10use sdl3::mouse::MouseButton;
11use serde::{Deserialize, Serialize};
12use smsgg_config::SmsGgButton;
13use snes_config::SnesButton;
14use std::fmt::Formatter;
15use std::sync::LazyLock;
16
17pub type ButtonMappingVec<'a, Button> = Vec<((Button, Player), &'a Vec<GenericInput>)>;
18pub type HotkeyMappingVec<'a> = Vec<(Hotkey, &'a Vec<GenericInput>)>;
19
20macro_rules! key_input {
21    ($key:ident) => {
22        Some(vec![GenericInput::Keyboard(KeyboardInput::Keycode(Keycode::$key))])
23    };
24}
25
26macro_rules! define_controller_mapping {
27    (
28        $name:ident,
29        $button_enum:ident,
30        [$($field:ident: $enum_value:ident),* $(,)?] $(,)?
31    ) => {
32        #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
33        pub struct $name {
34            $(
35                pub $field: Option<Vec<GenericInput>>,
36            )*
37        }
38
39        impl $name {
40            pub fn to_mapping_vec<'a>(&'a self, player: Player, out: &mut ButtonMappingVec<'a, $button_enum>) {
41                $(
42                    if let Some(mapping) = &self.$field {
43                        out.push((($button_enum::$enum_value, player), mapping));
44                    }
45                )*
46            }
47
48            #[must_use]
49            pub fn access_value(&mut self, button: $button_enum) -> Option<&mut Option<Vec<GenericInput>>> {
50                match button {
51                    $(
52                        $button_enum::$enum_value => Some(&mut self.$field),
53                    )*
54                    #[allow(unreachable_patterns)]
55                    _ => None,
56                }
57            }
58
59            #[must_use]
60            pub fn access_value_shared(&self, button: $button_enum) -> Option<&Option<Vec<GenericInput>>> {
61                match button {
62                    $(
63                        $button_enum::$enum_value => Some(&self.$field),
64                    )*
65                    #[allow(unreachable_patterns)]
66                    _ => None,
67                }
68            }
69
70            pub fn clone_from(&mut self, other: &Self, buttons: &[$button_enum]) {
71                for &button in buttons {
72                    if let Some(value) = self.access_value(button)
73                        && let Some(other_value) = other.access_value_shared(button)
74                    {
75                        *value = other_value.clone();
76                    }
77                }
78            }
79        }
80
81        impl std::fmt::Display for $name {
82            // Last `first_mapping = false` will be flagged as unused without this #[allow(..)]
83            #[allow(unused_assignments)]
84            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
85                fmt_input_mapping(&[
86                    $(
87                        ($button_enum::$enum_value, &self.$field),
88                    )*
89                ], f)
90            }
91        }
92    }
93}
94
95fn fmt_input_mapping<Button: std::fmt::Display>(
96    buttons: &[(Button, &Option<Vec<GenericInput>>)],
97    f: &mut Formatter<'_>,
98) -> std::fmt::Result {
99    write!(f, "{{ ")?;
100
101    let mut first_mapping = true;
102    for (button, mapping) in buttons {
103        let Some(mapping) = mapping else { continue };
104        if mapping.is_empty() {
105            continue;
106        }
107
108        if !first_mapping {
109            write!(f, ", ")?;
110        }
111        first_mapping = false;
112
113        write!(f, "{button} -> '")?;
114        fmt_input_mapping_field(mapping, f)?;
115        write!(f, "'")?;
116    }
117
118    write!(f, " }}")
119}
120
121fn fmt_input_mapping_field(mapping: &[GenericInput], f: &mut Formatter<'_>) -> std::fmt::Result {
122    if mapping.is_empty() {
123        return Ok(());
124    }
125
126    let mut first_input = true;
127    for input in mapping {
128        if !first_input {
129            write!(f, " + ")?;
130        }
131        first_input = false;
132
133        write!(f, "{input}")?;
134    }
135
136    Ok(())
137}
138
139macro_rules! impl_to_mapping_vec {
140    ($button:ty) => {
141        #[must_use]
142        pub fn to_mapping_vec(&self) -> ButtonMappingVec<'_, $button> {
143            let mut out = Vec::new();
144
145            self.mapping_1.to_mapping_vec(&mut out);
146            self.mapping_2.to_mapping_vec(&mut out);
147
148            out
149        }
150    };
151}
152
153macro_rules! impl_to_turbo_mapping_vec {
154    ($button:ty) => {
155        impl_to_turbo_mapping_vec!($button, [(One, p1_turbo), (Two, p2_turbo)]);
156    };
157    ($button:ty, [$(($player:ident, $field:ident)),* $(,)?]) => {
158        #[must_use]
159        pub fn to_turbo_mapping_vec(&self) -> ButtonMappingVec<'_, $button> {
160            let mut out = Vec::new();
161
162            for mapping in [&self.mapping_1, &self.mapping_2] {
163                $(
164                    mapping.$field.to_mapping_vec(Player::$player, &mut out);
165                )*
166            }
167
168            out
169        }
170    };
171}
172
173macro_rules! impl_player_mapping {
174    ($mapping:ty) => {
175        impl_player_mapping!($mapping, [(One, p1, p1_turbo), (Two, p2, p2_turbo)]);
176    };
177    ($mapping:ty, [$(($player:ident, $field:ident, $turbo_field:ident)),* $(,)?]) => {
178        #[must_use]
179        pub fn player_mapping(&mut self, player: Player, turbo: bool) -> Option<&mut $mapping> {
180            match (player, turbo) {
181                $(
182                    (Player::$player, false) => Some(&mut self.$field),
183                    (Player::$player, true) => Some(&mut self.$turbo_field),
184                )*
185                _ => None,
186            }
187        }
188    };
189}
190
191define_controller_mapping!(SmsGgControllerMapping, SmsGgButton, [
192    up: Up,
193    left: Left,
194    right: Right,
195    down: Down,
196    button1: Button1,
197    button2: Button2,
198]);
199
200impl SmsGgControllerMapping {
201    #[must_use]
202    pub fn keyboard_arrows() -> Self {
203        Self {
204            up: key_input!(Up),
205            left: key_input!(Left),
206            right: key_input!(Right),
207            down: key_input!(Down),
208            button1: key_input!(S),
209            button2: key_input!(A),
210        }
211    }
212
213    #[must_use]
214    pub fn keyboard_wasd() -> Self {
215        Self {
216            up: key_input!(W),
217            left: key_input!(A),
218            right: key_input!(D),
219            down: key_input!(S),
220            button1: key_input!(K),
221            button2: key_input!(L),
222        }
223    }
224
225    #[must_use]
226    pub fn keyboard_pause() -> Option<Vec<GenericInput>> {
227        key_input!(Return)
228    }
229}
230
231#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
232#[serde(default)]
233pub struct SmsGgInputMapping {
234    pub p1: SmsGgControllerMapping,
235    pub p2: SmsGgControllerMapping,
236    pub p1_turbo: SmsGgControllerMapping,
237    pub p2_turbo: SmsGgControllerMapping,
238    #[cfg_display(debug_fmt)]
239    pub pause: Option<Vec<GenericInput>>,
240}
241
242impl SmsGgInputMapping {
243    impl_player_mapping!(SmsGgControllerMapping);
244
245    pub fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, SmsGgButton>) {
246        self.p1.to_mapping_vec(Player::One, out);
247        self.p2.to_mapping_vec(Player::Two, out);
248
249        if let Some(pause) = &self.pause {
250            out.push(((SmsGgButton::Pause, Player::One), pause));
251        }
252    }
253}
254
255#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
256#[serde(default)]
257pub struct SmsGgInputConfig {
258    #[cfg_display(indent_nested)]
259    pub mapping_1: SmsGgInputMapping,
260    #[cfg_display(indent_nested)]
261    pub mapping_2: SmsGgInputMapping,
262}
263
264impl SmsGgInputConfig {
265    impl_to_mapping_vec!(SmsGgButton);
266
267    impl_to_turbo_mapping_vec!(SmsGgButton);
268}
269
270fn default_smsgg_mapping_1() -> SmsGgInputMapping {
271    SmsGgInputMapping {
272        p1: SmsGgControllerMapping::keyboard_arrows(),
273        p2: SmsGgControllerMapping::default(),
274        p1_turbo: SmsGgControllerMapping::default(),
275        p2_turbo: SmsGgControllerMapping::default(),
276        pause: key_input!(Return),
277    }
278}
279
280impl Default for SmsGgInputConfig {
281    fn default() -> Self {
282        Self { mapping_1: default_smsgg_mapping_1(), mapping_2: SmsGgInputMapping::default() }
283    }
284}
285
286define_controller_mapping!(GenesisControllerMapping, GenesisButton, [
287    up: Up,
288    left: Left,
289    right: Right,
290    down: Down,
291    a: A,
292    b: B,
293    c: C,
294    x: X,
295    y: Y,
296    z: Z,
297    start: Start,
298    mode: Mode,
299    mega_mouse_left: MegaMouseLeft,
300    mega_mouse_right: MegaMouseRight,
301    mega_mouse_middle: MegaMouseMiddle,
302    mega_mouse_start: MegaMouseStart,
303    xe1ap_analog_left: Xe1apAnalogLeft,
304    xe1ap_analog_right: Xe1apAnalogRight,
305    xe1ap_analog_up: Xe1apAnalogUp,
306    xe1ap_analog_down: Xe1apAnalogDown,
307    xe1ap_slider_forward: Xe1apSliderForward,
308    xe1ap_slider_backward: Xe1apSliderBackward,
309    xe1ap_a: Xe1apA,
310    xe1ap_b: Xe1apB,
311    xe1ap_c: Xe1apC,
312    xe1ap_d: Xe1apD,
313    xe1ap_e1: Xe1apE1,
314    xe1ap_e2: Xe1apE2,
315    xe1ap_ap: Xe1apAp,
316    xe1ap_bp: Xe1apBp,
317    xe1ap_start: Xe1apStart,
318    xe1ap_select: Xe1apSelect,
319]);
320
321impl GenesisControllerMapping {
322    #[must_use]
323    pub fn keyboard_arrows() -> Self {
324        Self {
325            up: key_input!(Up),
326            left: key_input!(Left),
327            right: key_input!(Right),
328            down: key_input!(Down),
329            a: key_input!(A),
330            b: key_input!(S),
331            c: key_input!(D),
332            x: key_input!(Q),
333            y: key_input!(W),
334            z: key_input!(E),
335            start: key_input!(Return),
336            mode: key_input!(RShift),
337            mega_mouse_left: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
338            mega_mouse_right: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
339            mega_mouse_middle: Some(vec![GenericInput::Mouse(MouseButton::Middle)]),
340            mega_mouse_start: key_input!(Return),
341            xe1ap_analog_left: None,
342            xe1ap_analog_right: None,
343            xe1ap_analog_up: None,
344            xe1ap_analog_down: None,
345            xe1ap_slider_forward: None,
346            xe1ap_slider_backward: None,
347            xe1ap_a: None,
348            xe1ap_b: None,
349            xe1ap_c: None,
350            xe1ap_d: None,
351            xe1ap_e1: None,
352            xe1ap_e2: None,
353            xe1ap_ap: None,
354            xe1ap_bp: None,
355            xe1ap_start: None,
356            xe1ap_select: None,
357        }
358    }
359
360    #[must_use]
361    pub fn keyboard_wasd() -> Self {
362        Self {
363            up: key_input!(W),
364            left: key_input!(A),
365            right: key_input!(D),
366            down: key_input!(S),
367            a: key_input!(J),
368            b: key_input!(K),
369            c: key_input!(L),
370            x: key_input!(U),
371            y: key_input!(I),
372            z: key_input!(O),
373            start: key_input!(Return),
374            mode: key_input!(RShift),
375            mega_mouse_left: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
376            mega_mouse_right: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
377            mega_mouse_middle: Some(vec![GenericInput::Mouse(MouseButton::Middle)]),
378            mega_mouse_start: key_input!(Return),
379            xe1ap_analog_left: None,
380            xe1ap_analog_right: None,
381            xe1ap_analog_up: None,
382            xe1ap_analog_down: None,
383            xe1ap_slider_forward: None,
384            xe1ap_slider_backward: None,
385            xe1ap_a: None,
386            xe1ap_b: None,
387            xe1ap_c: None,
388            xe1ap_d: None,
389            xe1ap_e1: None,
390            xe1ap_e2: None,
391            xe1ap_ap: None,
392            xe1ap_bp: None,
393            xe1ap_start: None,
394            xe1ap_select: None,
395        }
396    }
397
398    pub fn clone_from_type(&mut self, other: &Self, controller_type: GenesisControllerType) {
399        static GAMEPAD_BUTTONS: LazyLock<Vec<GenesisButton>> = LazyLock::new(|| {
400            GenesisButton::ALL.into_iter().filter(|&button| button.is_gamepad()).collect()
401        });
402
403        static MOUSE_BUTTONS: LazyLock<Vec<GenesisButton>> = LazyLock::new(|| {
404            GenesisButton::ALL.into_iter().filter(|&button| button.is_mouse()).collect()
405        });
406
407        static XE1AP_BUTTONS: LazyLock<Vec<GenesisButton>> = LazyLock::new(|| {
408            GenesisButton::ALL.into_iter().filter(|&button| button.is_xe1ap()).collect()
409        });
410
411        match controller_type {
412            GenesisControllerType::MegaMouse => self.clone_from(other, &MOUSE_BUTTONS),
413            GenesisControllerType::Xe1ap => self.clone_from(other, &XE1AP_BUTTONS),
414            GenesisControllerType::ThreeButton
415            | GenesisControllerType::SixButton
416            | GenesisControllerType::None => self.clone_from(other, &GAMEPAD_BUTTONS),
417        }
418    }
419}
420
421#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
422#[serde(default)]
423pub struct GenesisInputMapping {
424    #[cfg_display(indent_nested)]
425    pub p1: GenesisControllerMapping,
426    #[cfg_display(indent_nested)]
427    pub p2: GenesisControllerMapping,
428    #[cfg_display(indent_nested)]
429    pub p1_turbo: GenesisControllerMapping,
430    #[cfg_display(indent_nested)]
431    pub p2_turbo: GenesisControllerMapping,
432}
433
434impl GenesisInputMapping {
435    impl_player_mapping!(GenesisControllerMapping);
436
437    pub fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, GenesisButton>) {
438        self.p1.to_mapping_vec(Player::One, out);
439        self.p2.to_mapping_vec(Player::Two, out);
440    }
441}
442
443#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
444#[serde(default)]
445pub struct GenesisInputConfig {
446    pub p1_type: GenesisControllerType,
447    pub p2_type: GenesisControllerType,
448    #[cfg_display(indent_nested)]
449    pub mapping_1: GenesisInputMapping,
450    #[cfg_display(indent_nested)]
451    pub mapping_2: GenesisInputMapping,
452}
453
454impl GenesisInputConfig {
455    impl_to_mapping_vec!(GenesisButton);
456
457    impl_to_turbo_mapping_vec!(GenesisButton);
458}
459
460fn default_genesis_mapping_1() -> GenesisInputMapping {
461    GenesisInputMapping {
462        p1: GenesisControllerMapping::keyboard_arrows(),
463        p2: GenesisControllerMapping::default(),
464        p1_turbo: GenesisControllerMapping::default(),
465        p2_turbo: GenesisControllerMapping::default(),
466    }
467}
468
469impl Default for GenesisInputConfig {
470    fn default() -> Self {
471        Self {
472            p1_type: GenesisControllerType::default(),
473            p2_type: GenesisControllerType::None,
474            mapping_1: default_genesis_mapping_1(),
475            mapping_2: GenesisInputMapping::default(),
476        }
477    }
478}
479
480define_controller_mapping!(NesControllerMapping, NesButton, [
481    up: Up,
482    left: Left,
483    right: Right,
484    down: Down,
485    a: A,
486    b: B,
487    start: Start,
488    select: Select,
489]);
490
491impl NesControllerMapping {
492    #[must_use]
493    pub fn keyboard_arrows() -> Self {
494        Self {
495            up: key_input!(Up),
496            left: key_input!(Left),
497            right: key_input!(Right),
498            down: key_input!(Down),
499            a: key_input!(A),
500            b: key_input!(S),
501            start: key_input!(Return),
502            select: key_input!(RShift),
503        }
504    }
505
506    #[must_use]
507    pub fn keyboard_wasd() -> Self {
508        Self {
509            up: key_input!(W),
510            left: key_input!(A),
511            right: key_input!(D),
512            down: key_input!(S),
513            a: key_input!(L),
514            b: key_input!(K),
515            start: key_input!(Return),
516            select: key_input!(RShift),
517        }
518    }
519}
520
521define_controller_mapping!(NesZapperMapping, NesButton, [
522    fire: ZapperFire,
523    force_offscreen: ZapperForceOffscreen,
524]);
525
526impl NesZapperMapping {
527    #[must_use]
528    pub fn mouse() -> Self {
529        Self {
530            fire: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
531            force_offscreen: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
532        }
533    }
534}
535
536#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
537#[serde(default)]
538pub struct NesInputMapping {
539    #[cfg_display(indent_nested)]
540    pub p1: NesControllerMapping,
541    #[cfg_display(indent_nested)]
542    pub p2: NesControllerMapping,
543    #[cfg_display(indent_nested)]
544    pub p1_turbo: NesControllerMapping,
545    #[cfg_display(indent_nested)]
546    pub p2_turbo: NesControllerMapping,
547    #[cfg_display(indent_nested)]
548    pub zapper: NesZapperMapping,
549}
550
551impl NesInputMapping {
552    impl_player_mapping!(NesControllerMapping);
553
554    pub fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, NesButton>) {
555        self.p1.to_mapping_vec(Player::One, out);
556        self.p2.to_mapping_vec(Player::Two, out);
557        self.zapper.to_mapping_vec(Player::One, out);
558    }
559}
560
561#[derive(
562    Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, EnumDisplay, EnumAll,
563)]
564#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))]
565pub enum NesControllerType {
566    #[default]
567    Gamepad,
568    Zapper,
569}
570
571#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
572#[serde(default)]
573pub struct NesInputConfig {
574    pub p2_type: NesControllerType,
575    #[cfg_display(indent_nested)]
576    pub mapping_1: NesInputMapping,
577    #[cfg_display(indent_nested)]
578    pub mapping_2: NesInputMapping,
579}
580
581impl NesInputConfig {
582    impl_to_mapping_vec!(NesButton);
583
584    impl_to_turbo_mapping_vec!(NesButton);
585}
586
587fn default_nes_mapping_1() -> NesInputMapping {
588    NesInputMapping {
589        p1: NesControllerMapping::keyboard_arrows(),
590        p2: NesControllerMapping::default(),
591        p1_turbo: NesControllerMapping::default(),
592        p2_turbo: NesControllerMapping::default(),
593        zapper: NesZapperMapping::mouse(),
594    }
595}
596
597impl Default for NesInputConfig {
598    fn default() -> Self {
599        Self {
600            p2_type: NesControllerType::default(),
601            mapping_1: default_nes_mapping_1(),
602            mapping_2: NesInputMapping::default(),
603        }
604    }
605}
606
607define_controller_mapping!(SnesControllerMapping, SnesButton, [
608    up: Up,
609    left: Left,
610    right: Right,
611    down: Down,
612    a: A,
613    b: B,
614    x: X,
615    y: Y,
616    l: L,
617    r: R,
618    start: Start,
619    select: Select,
620    mouse_left: MouseLeft,
621    mouse_right: MouseRight,
622    super_scope_fire: SuperScopeFire,
623    super_scope_cursor: SuperScopeCursor,
624    super_scope_pause: SuperScopePause,
625    super_scope_turbo_toggle: SuperScopeTurboToggle,
626]);
627
628impl SnesControllerMapping {
629    #[must_use]
630    pub fn keyboard_arrows() -> Self {
631        Self {
632            up: key_input!(Up),
633            left: key_input!(Left),
634            right: key_input!(Right),
635            down: key_input!(Down),
636            a: key_input!(S),
637            b: key_input!(X),
638            x: key_input!(A),
639            y: key_input!(Z),
640            l: key_input!(D),
641            r: key_input!(C),
642            start: key_input!(Return),
643            select: key_input!(RShift),
644            mouse_left: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
645            mouse_right: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
646            super_scope_fire: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
647            super_scope_cursor: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
648            super_scope_pause: Some(vec![GenericInput::Mouse(MouseButton::Middle)]),
649            super_scope_turbo_toggle: key_input!(T),
650        }
651    }
652
653    #[must_use]
654    pub fn keyboard_wasd() -> Self {
655        Self {
656            up: key_input!(W),
657            left: key_input!(A),
658            right: key_input!(D),
659            down: key_input!(S),
660            a: key_input!(L),
661            b: key_input!(K),
662            x: key_input!(I),
663            y: key_input!(J),
664            l: key_input!(U),
665            r: key_input!(O),
666            start: key_input!(Return),
667            select: key_input!(RShift),
668            mouse_left: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
669            mouse_right: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
670            super_scope_fire: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
671            super_scope_cursor: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
672            super_scope_pause: Some(vec![GenericInput::Mouse(MouseButton::Middle)]),
673            super_scope_turbo_toggle: key_input!(T),
674        }
675    }
676
677    #[must_use]
678    pub fn super_scope_only() -> Self {
679        Self {
680            up: None,
681            left: None,
682            right: None,
683            down: None,
684            a: None,
685            b: None,
686            x: None,
687            y: None,
688            l: None,
689            r: None,
690            start: None,
691            select: None,
692            mouse_left: None,
693            mouse_right: None,
694            super_scope_fire: Some(vec![GenericInput::Mouse(MouseButton::Left)]),
695            super_scope_cursor: Some(vec![GenericInput::Mouse(MouseButton::Right)]),
696            super_scope_pause: Some(vec![GenericInput::Mouse(MouseButton::Middle)]),
697            super_scope_turbo_toggle: key_input!(T),
698        }
699    }
700}
701
702#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
703#[serde(default)]
704pub struct SnesInputMapping {
705    #[cfg_display(indent_nested)]
706    pub p1: SnesControllerMapping,
707    #[cfg_display(indent_nested)]
708    pub p2: SnesControllerMapping,
709    #[cfg_display(indent_nested)]
710    pub p1_turbo: SnesControllerMapping,
711    #[cfg_display(indent_nested)]
712    pub p2_turbo: SnesControllerMapping,
713}
714
715impl SnesInputMapping {
716    impl_player_mapping!(SnesControllerMapping);
717
718    pub fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, SnesButton>) {
719        self.p1.to_mapping_vec(Player::One, out);
720        self.p2.to_mapping_vec(Player::Two, out);
721    }
722}
723
724#[derive(
725    Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, EnumDisplay, EnumAll,
726)]
727#[cfg_attr(feature = "clap", derive(jgenesis_proc_macros::CustomValueEnum))]
728pub enum SnesControllerType {
729    #[default]
730    Gamepad,
731    Mouse,
732    SuperScope,
733    None,
734}
735
736#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
737#[serde(default)]
738pub struct SnesInputConfig {
739    pub p1_type: SnesControllerType,
740    pub p2_type: SnesControllerType,
741    #[cfg_display(indent_nested)]
742    pub mapping_1: SnesInputMapping,
743    #[cfg_display(indent_nested)]
744    pub mapping_2: SnesInputMapping,
745}
746
747impl SnesInputConfig {
748    impl_to_mapping_vec!(SnesButton);
749
750    impl_to_turbo_mapping_vec!(SnesButton);
751}
752
753fn default_snes_mapping_1() -> SnesInputMapping {
754    SnesInputMapping {
755        p1: SnesControllerMapping::keyboard_arrows(),
756        p2: SnesControllerMapping::super_scope_only(),
757        p1_turbo: SnesControllerMapping::default(),
758        p2_turbo: SnesControllerMapping::default(),
759    }
760}
761
762impl Default for SnesInputConfig {
763    fn default() -> Self {
764        Self {
765            p1_type: SnesControllerType::Gamepad,
766            p2_type: SnesControllerType::None,
767            mapping_1: default_snes_mapping_1(),
768            mapping_2: SnesInputMapping::default(),
769        }
770    }
771}
772
773define_controller_mapping!(GameBoyInputMapping, GameBoyButton, [
774    up: Up,
775    left: Left,
776    right: Right,
777    down: Down,
778    a: A,
779    b: B,
780    start: Start,
781    select: Select,
782]);
783
784impl GameBoyInputMapping {
785    #[must_use]
786    pub fn keyboard_arrows() -> Self {
787        Self {
788            up: key_input!(Up),
789            left: key_input!(Left),
790            right: key_input!(Right),
791            down: key_input!(Down),
792            a: key_input!(A),
793            b: key_input!(S),
794            start: key_input!(Return),
795            select: key_input!(RShift),
796        }
797    }
798
799    #[must_use]
800    pub fn keyboard_wasd() -> Self {
801        Self {
802            up: key_input!(W),
803            left: key_input!(A),
804            right: key_input!(D),
805            down: key_input!(S),
806            a: key_input!(L),
807            b: key_input!(K),
808            start: key_input!(Return),
809            select: key_input!(RShift),
810        }
811    }
812}
813
814#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
815#[serde(default)]
816pub struct GameBoyInputConfig {
817    #[cfg_display(indent_nested)]
818    pub mapping_1: GameBoyInputMapping,
819    #[cfg_display(indent_nested)]
820    pub mapping_2: GameBoyInputMapping,
821    #[cfg_display(indent_nested)]
822    pub mapping_1_turbo: GameBoyInputMapping,
823    #[cfg_display(indent_nested)]
824    pub mapping_2_turbo: GameBoyInputMapping,
825}
826
827impl GameBoyInputConfig {
828    #[must_use]
829    pub fn to_mapping_vec(&self) -> ButtonMappingVec<'_, GameBoyButton> {
830        let mut out = Vec::new();
831
832        self.mapping_1.to_mapping_vec(Player::One, &mut out);
833        self.mapping_2.to_mapping_vec(Player::One, &mut out);
834
835        out
836    }
837
838    #[must_use]
839    pub fn to_turbo_mapping_vec(&self) -> ButtonMappingVec<'_, GameBoyButton> {
840        let mut out = Vec::new();
841
842        self.mapping_1_turbo.to_mapping_vec(Player::One, &mut out);
843        self.mapping_2_turbo.to_mapping_vec(Player::One, &mut out);
844
845        out
846    }
847}
848
849fn default_gb_mapping_1() -> GameBoyInputMapping {
850    GameBoyInputMapping::keyboard_arrows()
851}
852
853impl Default for GameBoyInputConfig {
854    fn default() -> Self {
855        Self {
856            mapping_1: default_gb_mapping_1(),
857            mapping_2: GameBoyInputMapping::default(),
858            mapping_1_turbo: GameBoyInputMapping::default(),
859            mapping_2_turbo: GameBoyInputMapping::default(),
860        }
861    }
862}
863
864define_controller_mapping!(GbaJoypadMapping, GbaButton, [
865    up: Up,
866    left: Left,
867    right: Right,
868    down: Down,
869    a: A,
870    b: B,
871    l: L,
872    r: R,
873    start: Start,
874    select: Select,
875]);
876
877impl GbaJoypadMapping {
878    #[must_use]
879    pub fn keyboard_arrows() -> Self {
880        Self {
881            up: key_input!(Up),
882            left: key_input!(Left),
883            right: key_input!(Right),
884            down: key_input!(Down),
885            a: key_input!(A),
886            b: key_input!(S),
887            l: key_input!(Q),
888            r: key_input!(W),
889            start: key_input!(Return),
890            select: key_input!(RShift),
891        }
892    }
893
894    #[must_use]
895    pub fn keyboard_wasd() -> Self {
896        Self {
897            up: key_input!(W),
898            left: key_input!(A),
899            right: key_input!(D),
900            down: key_input!(S),
901            a: key_input!(L),
902            b: key_input!(K),
903            l: key_input!(I),
904            r: key_input!(O),
905            start: key_input!(Return),
906            select: key_input!(RShift),
907        }
908    }
909}
910
911define_controller_mapping!(GbaSolarMapping, GbaButton, [
912    increase_brightness: SolarIncreaseBrightness,
913    decrease_brightness: SolarDecreaseBrightness,
914    min_brightness: SolarMinBrightness,
915    max_brightness: SolarMaxBrightness,
916]);
917
918#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
919#[serde(default)]
920pub struct GbaInputMapping {
921    #[cfg_display(indent_nested)]
922    pub joypad: GbaJoypadMapping,
923    #[cfg_display(indent_nested)]
924    pub solar: GbaSolarMapping,
925}
926
927impl GbaInputMapping {
928    fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, GbaButton>) {
929        self.joypad.to_mapping_vec(Player::One, out);
930        self.solar.to_mapping_vec(Player::One, out);
931    }
932}
933
934#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
935#[serde(default)]
936pub struct GbaInputConfig {
937    #[cfg_display(indent_nested)]
938    pub mapping_1: GbaInputMapping,
939    #[cfg_display(indent_nested)]
940    pub mapping_2: GbaInputMapping,
941    #[cfg_display(indent_nested)]
942    pub mapping_1_turbo: GbaInputMapping,
943    #[cfg_display(indent_nested)]
944    pub mapping_2_turbo: GbaInputMapping,
945}
946
947impl GbaInputConfig {
948    #[must_use]
949    pub fn to_mapping_vec(&self) -> ButtonMappingVec<'_, GbaButton> {
950        let mut out = Vec::new();
951
952        self.mapping_1.to_mapping_vec(&mut out);
953        self.mapping_2.to_mapping_vec(&mut out);
954
955        out
956    }
957
958    #[must_use]
959    pub fn to_turbo_mapping_vec(&self) -> ButtonMappingVec<'_, GbaButton> {
960        let mut out = Vec::new();
961
962        self.mapping_1_turbo.to_mapping_vec(&mut out);
963        self.mapping_2_turbo.to_mapping_vec(&mut out);
964
965        out
966    }
967}
968
969fn default_gba_mapping_1() -> GbaInputMapping {
970    GbaInputMapping {
971        joypad: GbaJoypadMapping::keyboard_arrows(),
972        solar: GbaSolarMapping::default(),
973    }
974}
975
976impl Default for GbaInputConfig {
977    fn default() -> Self {
978        Self {
979            mapping_1: default_gba_mapping_1(),
980            mapping_2: GbaInputMapping::default(),
981            mapping_1_turbo: GbaInputMapping::default(),
982            mapping_2_turbo: GbaInputMapping::default(),
983        }
984    }
985}
986
987define_controller_mapping!(PceJoypadMapping, PceButton, [
988    up: Up,
989    left: Left,
990    right: Right,
991    down: Down,
992    button1: Button1,
993    button2: Button2,
994    run: Run,
995    select: Select,
996]);
997
998impl PceJoypadMapping {
999    #[must_use]
1000    pub fn keyboard_arrows() -> Self {
1001        Self {
1002            up: key_input!(Up),
1003            left: key_input!(Left),
1004            right: key_input!(Right),
1005            down: key_input!(Down),
1006            button1: key_input!(A),
1007            button2: key_input!(S),
1008            run: key_input!(Return),
1009            select: key_input!(RShift),
1010        }
1011    }
1012
1013    #[must_use]
1014    pub fn keyboard_wasd() -> Self {
1015        Self {
1016            up: key_input!(W),
1017            left: key_input!(A),
1018            right: key_input!(S),
1019            down: key_input!(D),
1020            button1: key_input!(L),
1021            button2: key_input!(K),
1022            run: key_input!(Return),
1023            select: key_input!(RShift),
1024        }
1025    }
1026}
1027
1028#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, ConfigDisplay)]
1029#[serde(default)]
1030pub struct PceInputMapping {
1031    #[cfg_display(indent_nested)]
1032    pub p1: PceJoypadMapping,
1033    #[cfg_display(indent_nested)]
1034    pub p2: PceJoypadMapping,
1035    #[cfg_display(indent_nested)]
1036    pub p3: PceJoypadMapping,
1037    #[cfg_display(indent_nested)]
1038    pub p4: PceJoypadMapping,
1039    #[cfg_display(indent_nested)]
1040    pub p5: PceJoypadMapping,
1041    #[cfg_display(indent_nested)]
1042    pub p1_turbo: PceJoypadMapping,
1043    #[cfg_display(indent_nested)]
1044    pub p2_turbo: PceJoypadMapping,
1045    #[cfg_display(indent_nested)]
1046    pub p3_turbo: PceJoypadMapping,
1047    #[cfg_display(indent_nested)]
1048    pub p4_turbo: PceJoypadMapping,
1049    #[cfg_display(indent_nested)]
1050    pub p5_turbo: PceJoypadMapping,
1051}
1052
1053impl PceInputMapping {
1054    impl_player_mapping!(
1055        PceJoypadMapping,
1056        [
1057            (One, p1, p1_turbo),
1058            (Two, p2, p2_turbo),
1059            (Three, p3, p3_turbo),
1060            (Four, p4, p4_turbo),
1061            (Five, p5, p5_turbo),
1062        ]
1063    );
1064
1065    pub fn to_mapping_vec<'a>(&'a self, out: &mut ButtonMappingVec<'a, PceButton>) {
1066        self.p1.to_mapping_vec(Player::One, out);
1067        self.p2.to_mapping_vec(Player::Two, out);
1068        self.p3.to_mapping_vec(Player::Three, out);
1069        self.p4.to_mapping_vec(Player::Four, out);
1070        self.p5.to_mapping_vec(Player::Five, out);
1071    }
1072}
1073
1074#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
1075#[serde(default)]
1076pub struct PceInputConfig {
1077    #[cfg_display(indent_nested)]
1078    pub mapping_1: PceInputMapping,
1079    #[cfg_display(indent_nested)]
1080    pub mapping_2: PceInputMapping,
1081}
1082
1083impl PceInputConfig {
1084    impl_to_mapping_vec!(PceButton);
1085
1086    impl_to_turbo_mapping_vec!(
1087        PceButton,
1088        [(One, p1_turbo), (Two, p2_turbo), (Three, p3_turbo), (Four, p4_turbo), (Five, p5_turbo)]
1089    );
1090}
1091
1092impl Default for PceInputConfig {
1093    fn default() -> Self {
1094        Self {
1095            mapping_1: PceInputMapping {
1096                p1: PceJoypadMapping::keyboard_arrows(),
1097                p2: PceJoypadMapping::default(),
1098                p3: PceJoypadMapping::default(),
1099                p4: PceJoypadMapping::default(),
1100                p5: PceJoypadMapping::default(),
1101                p1_turbo: PceJoypadMapping::default(),
1102                p2_turbo: PceJoypadMapping::default(),
1103                p3_turbo: PceJoypadMapping::default(),
1104                p4_turbo: PceJoypadMapping::default(),
1105                p5_turbo: PceJoypadMapping::default(),
1106            },
1107            mapping_2: PceInputMapping::default(),
1108        }
1109    }
1110}
1111
1112macro_rules! define_hotkey_mapping {
1113    (@default none) => {
1114        None
1115    };
1116    (@default $default:ident) => {
1117        Some(vec![GenericInput::Keyboard(KeyboardInput::Keycode(Keycode::$default))])
1118    };
1119    (@default ($($default:ident $(+)?)*)) => {
1120        Some(vec![
1121            $(
1122                GenericInput::Keyboard(KeyboardInput::Keycode(Keycode::$default)),
1123            )*
1124        ])
1125    };
1126    ($($value:ident: $hotkey:ident $label:literal default $default:tt),* $(,)?) => {
1127        #[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
1128        pub struct HotkeyMapping {
1129            $(
1130                pub $value: Option<Vec<GenericInput>>,
1131            )*
1132        }
1133
1134        impl HotkeyMapping {
1135            #[must_use]
1136            pub fn default_keyboard() -> Self {
1137                Self {
1138                    $(
1139                        $value: define_hotkey_mapping!(@default $default),
1140                    )*
1141                }
1142            }
1143
1144            pub fn to_mapping_vec<'a>(&'a self, out: &mut HotkeyMappingVec<'a>) {
1145                $(
1146                    if let Some(mapping) = &self.$value {
1147                        out.push((Hotkey::$hotkey, mapping));
1148                    }
1149                )*
1150            }
1151
1152            #[must_use]
1153            pub fn access_value(&mut self, hotkey: Hotkey) -> &mut Option<Vec<GenericInput>> {
1154                match hotkey {
1155                    $(
1156                        Hotkey::$hotkey => &mut self.$value,
1157                    )*
1158                }
1159            }
1160        }
1161
1162        impl std::fmt::Display for HotkeyMapping {
1163            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1164                fmt_input_mapping(&[
1165                    $(
1166                        (Hotkey::$hotkey, &self.$value),
1167                    )*
1168                ], f)
1169            }
1170        }
1171
1172        impl Hotkey {
1173            #[must_use]
1174            pub fn label(self) -> &'static str {
1175                match self {
1176                    $(
1177                        Self::$hotkey => $label,
1178                    )*
1179                }
1180            }
1181        }
1182    };
1183}
1184
1185define_hotkey_mapping!(
1186    power_off: PowerOff "Power off emulated system" default Escape,
1187    exit: Exit "Exit application" default (LCtrl + Q),
1188    toggle_fullscreen: ToggleFullscreen "Toggle fullscreen" default F9,
1189    save_state: SaveState "Save state to current slot" default F5,
1190    load_state: LoadState "Load state from current slot" default F6,
1191    next_save_state_slot: NextSaveStateSlot "Next save state slot" default RightBracket,
1192    prev_save_state_slot: PrevSaveStateSlot "Previous save state slot" default LeftBracket,
1193    soft_reset: SoftReset "Soft reset" default F1,
1194    hard_reset: HardReset "Hard reset" default F2,
1195    pause: Pause "Pause" default P,
1196    step_frame: StepFrame "Step to next frame" default N,
1197    fast_forward: FastForward "Fast forward" default Tab,
1198    rewind: Rewind "Rewind" default Grave,
1199    cancel_mouse_input: CancelMouseInput "Cancel mouse input" default O,
1200    toggle_overclocking: ToggleOverclocking "Toggle overclocking enabled" default Semicolon,
1201    open_debugger: OpenDebugger "Open memory viewer" default Apostrophe,
1202    save_state_slot_0: SaveStateSlot0 "Save state to slot 0" default none,
1203    save_state_slot_1: SaveStateSlot1 "Save state to slot 1" default none,
1204    save_state_slot_2: SaveStateSlot2 "Save state to slot 2" default none,
1205    save_state_slot_3: SaveStateSlot3 "Save state to slot 3" default none,
1206    save_state_slot_4: SaveStateSlot4 "Save state to slot 4" default none,
1207    save_state_slot_5: SaveStateSlot5 "Save state to slot 5" default none,
1208    save_state_slot_6: SaveStateSlot6 "Save state to slot 6" default none,
1209    save_state_slot_7: SaveStateSlot7 "Save state to slot 7" default none,
1210    save_state_slot_8: SaveStateSlot8 "Save state to slot 8" default none,
1211    save_state_slot_9: SaveStateSlot9 "Save state to slot 9" default none,
1212    load_state_slot_0: LoadStateSlot0 "Load state from slot 0" default none,
1213    load_state_slot_1: LoadStateSlot1 "Load state from slot 1" default none,
1214    load_state_slot_2: LoadStateSlot2 "Load state from slot 2" default none,
1215    load_state_slot_3: LoadStateSlot3 "Load state from slot 3" default none,
1216    load_state_slot_4: LoadStateSlot4 "Load state from slot 4" default none,
1217    load_state_slot_5: LoadStateSlot5 "Load state from slot 5" default none,
1218    load_state_slot_6: LoadStateSlot6 "Load state from slot 6" default none,
1219    load_state_slot_7: LoadStateSlot7 "Load state from slot 7" default none,
1220    load_state_slot_8: LoadStateSlot8 "Load state from slot 8" default none,
1221    load_state_slot_9: LoadStateSlot9 "Load state from slot 9" default none,
1222);
1223
1224#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ConfigDisplay)]
1225#[serde(default)]
1226pub struct HotkeyConfig {
1227    #[cfg_display(indent_nested)]
1228    pub mapping_1: HotkeyMapping,
1229    #[cfg_display(indent_nested)]
1230    pub mapping_2: HotkeyMapping,
1231}
1232
1233impl HotkeyConfig {
1234    #[must_use]
1235    pub fn to_mapping_vec(&self) -> HotkeyMappingVec<'_> {
1236        let mut out = Vec::new();
1237
1238        self.mapping_1.to_mapping_vec(&mut out);
1239        self.mapping_2.to_mapping_vec(&mut out);
1240
1241        out
1242    }
1243}
1244
1245impl Default for HotkeyConfig {
1246    fn default() -> Self {
1247        Self { mapping_1: HotkeyMapping::default_keyboard(), mapping_2: HotkeyMapping::default() }
1248    }
1249}