@@ -8,12 +8,14 @@ pub struct MenuOption<T, S:AsRef<str>>{
88#[ derive( Debug , Clone , Copy ) ]
99pub enum EmulatorMenuOption {
1010 Resume ,
11+ Turbo ,
1112 Restart ,
1213 Shutdown
1314}
1415
15- pub const GAME_MENU_OPTIONS : [ MenuOption < EmulatorMenuOption , & str > ; 3 ] = [
16+ pub const GAME_MENU_OPTIONS : [ MenuOption < EmulatorMenuOption , & str > ; 4 ] = [
1617 MenuOption { prompt : "Resume" , value : EmulatorMenuOption :: Resume } ,
18+ MenuOption { prompt : "Turbo" , value : EmulatorMenuOption :: Turbo } ,
1719 MenuOption { prompt : "Restart" , value : EmulatorMenuOption :: Restart } ,
1820 MenuOption { prompt : "Shutdown" , value : EmulatorMenuOption :: Shutdown }
1921] ;
@@ -25,15 +27,22 @@ cfg_if::cfg_if!{ if #[cfg(feature = "std")]{
2527
2628 pub struct MagenBoyState {
2729 // Use atomic bool, normal bool doesnt works on arm (probably cause of the memory model)
28- pub running: AtomicBool ,
29- pub pause: AtomicBool ,
30- pub exit: AtomicBool ,
31- pub state_mutex: Mutex <( ) >
30+ pub running: AtomicBool ,
31+ pub turbo: AtomicBool ,
32+ pub pause: AtomicBool ,
33+ pub exit: AtomicBool ,
34+ pub state_mutex: Mutex <( ) >
3235 }
3336
3437 impl MagenBoyState {
3538 pub const fn new( ) -> Self {
36- Self { running: AtomicBool :: new( true ) , pause: AtomicBool :: new( false ) , exit: AtomicBool :: new( false ) , state_mutex: Mutex :: new( ( ) ) }
39+ Self {
40+ running: AtomicBool :: new( true ) ,
41+ turbo: AtomicBool :: new( false ) ,
42+ pause: AtomicBool :: new( false ) ,
43+ exit: AtomicBool :: new( false ) ,
44+ state_mutex: Mutex :: new( ( ) )
45+ }
3746 }
3847 }
3948
@@ -47,9 +56,19 @@ cfg_if::cfg_if!{ if #[cfg(feature = "std")]{
4756 Self { provider, header }
4857 }
4958
50- pub fn pop_game_menu<GFX : GfxDevice >( & mut self , state: & MagenBoyState , gfx_device: & mut GFX , receiver: crossbeam_channel:: Receiver <usize >) {
59+ pub fn pop_game_menu<GFX : GfxDevice >(
60+ & mut self ,
61+ state: & MagenBoyState ,
62+ gfx_device: & mut GFX ,
63+ receiver: crossbeam_channel:: Receiver <usize >
64+ ) {
5165 match self . get_game_menu_selection( state, gfx_device, receiver) {
5266 EmulatorMenuOption :: Resume => { } ,
67+ EmulatorMenuOption :: Turbo => {
68+ let new_turbo_state = !state. turbo. load( std:: sync:: atomic:: Ordering :: Relaxed ) ;
69+ state. turbo. store( new_turbo_state, std:: sync:: atomic:: Ordering :: Relaxed ) ;
70+ log:: info!( "Turbo mode is: {new_turbo_state}" ) ;
71+ } ,
5372 EmulatorMenuOption :: Restart => state. running. store( false , std:: sync:: atomic:: Ordering :: Relaxed ) ,
5473 EmulatorMenuOption :: Shutdown => {
5574 state. running. store( false , std:: sync:: atomic:: Ordering :: Relaxed ) ;
@@ -58,7 +77,12 @@ cfg_if::cfg_if!{ if #[cfg(feature = "std")]{
5877 }
5978 }
6079
61- fn get_game_menu_selection<GFX : GfxDevice >( & mut self , state: & MagenBoyState , gfx_device: & mut GFX , emulation_framebuffer_channel: crossbeam_channel:: Receiver <usize >) ->& EmulatorMenuOption {
80+ fn get_game_menu_selection<GFX : GfxDevice >(
81+ & mut self ,
82+ state: & MagenBoyState ,
83+ gfx_device: & mut GFX ,
84+ emulation_framebuffer_channel: crossbeam_channel:: Receiver <usize >
85+ ) -> & EmulatorMenuOption {
6286 let menu_renderer = joypad_gfx_menu:: GfxDeviceMenuRenderer :: new( gfx_device) ;
6387
6488 let mut menu = JoypadMenu :: new( & GAME_MENU_OPTIONS , & self . header, menu_renderer) ;
@@ -67,10 +91,14 @@ cfg_if::cfg_if!{ if #[cfg(feature = "std")]{
6791 state. pause. store( true , std:: sync:: atomic:: Ordering :: SeqCst ) ;
6892 loop {
6993 if let Ok ( _lock) = state. state_mutex. try_lock( ) {
94+ // Turn off turbo to have a regular speed menu
95+ let last_turbo = state. turbo. swap( false , core:: sync:: atomic:: Ordering :: Relaxed ) ;
7096 let selection = menu. get_menu_selection( & mut self . provider) ;
97+ // restore turbo state
98+ state. turbo. store( last_turbo, core:: sync:: atomic:: Ordering :: Relaxed ) ;
7199 state. pause. store( false , std:: sync:: atomic:: Ordering :: SeqCst ) ;
72100 return selection;
73- } else{
101+ } else {
74102 // try recv in order to clear frames from the channel
75103 // in order to not block the emualtion thread and allow it to finish the frame
76104 let _ = emulation_framebuffer_channel. try_recv( ) ;
@@ -80,7 +108,11 @@ cfg_if::cfg_if!{ if #[cfg(feature = "std")]{
80108
81109 }
82110
83- pub fn get_rom_selection<MR : MenuRenderer <PathBuf , String >, JP : MenuJoypadProvider + JoypadProvider >( roms_path: & str , menu_renderer: MR , jp: & mut JP ) ->String {
111+ pub fn get_rom_selection<MR : MenuRenderer <PathBuf , String >, JP : MenuJoypadProvider + JoypadProvider >(
112+ roms_path: & str ,
113+ menu_renderer: MR ,
114+ jp: & mut JP
115+ ) -> String {
84116 let mut menu_options = Vec :: new( ) ;
85117 let dir_entries = std:: fs:: read_dir( roms_path) . expect( std:: format!( "Error openning the roms directory: {}" , roms_path) . as_str( ) ) ;
86118 for entry in dir_entries{
0 commit comments