1use crate::input::Pins; 2use bincode::{Decode, Encode}; 3use genesis_config::GenesisJoypadState; 4 5#[derive(Debug, Clone, Encode, Decode)] 6pub struct ThreeButtonState { 7 pub joypad: GenesisJoypadState, 8} 9 10impl ThreeButtonState { 11 pub fn new(joypad: GenesisJoypadState) -> Self { 12 Self { joypad } 13 } 14 15 pub fn update_pins(&self, pins: &mut Pins) { 16 if pins.th() { 17 // B, C, and directional inputs 18 pins.input_tr(!self.joypad.c); 19 pins.input_tl(!self.joypad.b); 20 pins.input_d3(!self.joypad.right); 21 pins.input_d2(!self.joypad.left); 22 pins.input_d1(!self.joypad.down); 23 pins.input_d0(!self.joypad.up); 24 } else { 25 // A and start (and up/down) 26 pins.input_tr(!self.joypad.start); 27 pins.input_tl(!self.joypad.a); 28 pins.input_d3(false); 29 pins.input_d2(false); 30 pins.input_d1(!self.joypad.down); 31 pins.input_d0(!self.joypad.up); 32 } 33 } 34} 35 36#[derive(Debug, Clone, Encode, Decode)] 37pub struct SixButtonState { 38 pub joypad: GenesisJoypadState, 39 th_flip_count: u8, 40 flip_reset_counter: u32, 41 last_th: bool, 42} 43 44impl SixButtonState { 45 // Produces roughly the expected timeout value in Joystick Test Program (PD), about 1.58ms 46 const FLIP_COUNTER_CYCLES: u32 = 12150; 47 48 pub fn new(joypad: GenesisJoypadState) -> Self { 49 Self { joypad, th_flip_count: 0, flip_reset_counter: 0, last_th: true } 50 } 51 52 pub fn update_pins(&mut self, pins: &mut Pins) { 53 // 6-button controller cycles through 5 different modes whenever TH flips from 0 to 1, 54 // resetting after ~1.5ms have passed without such a flip 55 let th = pins.th(); 56 if !self.last_th && th { 57 self.th_flip_count = (self.th_flip_count + 1) % 5; 58 self.flip_reset_counter = Self::FLIP_COUNTER_CYCLES; 59 } 60 self.last_th = th; 61 62 // TR and TL are always set the same way as 3-button 63 if th { 64 pins.input_tr(!self.joypad.c); 65 pins.input_tl(!self.joypad.b); 66 } else { 67 pins.input_tr(!self.joypad.start); 68 pins.input_tl(!self.joypad.a); 69 } 70 71 match (self.th_flip_count, th) { 72 (0..=2 | 4, true) => { 73 // 3-button: B, C, and directional inputs 74 pins.input_d3(!self.joypad.right); 75 pins.input_d2(!self.joypad.left); 76 pins.input_d1(!self.joypad.down); 77 pins.input_d0(!self.joypad.up); 78 } 79 (0 | 1 | 4, false) => { 80 // 3-button: A and Start (and up/down) 81 pins.input_d3(false); 82 pins.input_d2(false); 83 pins.input_d1(!self.joypad.down); 84 pins.input_d0(!self.joypad.up); 85 } 86 (2, false) => { 87 // 6-button: A, Start, and all 0s in the lower bits 88 pins.input_data_nibble(0b0000); 89 } 90 (3, true) => { 91 // 6-button: New buttons (and B and C) 92 pins.input_d3(!self.joypad.mode); 93 pins.input_d2(!self.joypad.x); 94 pins.input_d1(!self.joypad.y); 95 pins.input_d0(!self.joypad.z); 96 } 97 (3, false) => { 98 // 6-button: A, Start, and all 1s in the lower bits 99 pins.input_data_nibble(0b1111); 100 } 101 _ => panic!("th_flip_count should always be <= 4, was {}", self.th_flip_count), 102 } 103 } 104 105 pub fn tick(&mut self, m68k_cycles: u32, pins: &mut Pins) { 106 if self.flip_reset_counter == 0 { 107 return; 108 } 109 110 self.flip_reset_counter = self.flip_reset_counter.saturating_sub(m68k_cycles); 111 if self.flip_reset_counter == 0 { 112 self.th_flip_count = 0; 113 self.update_pins(pins); 114 } 115 } 116}