1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #include "NstInpDevice.hpp" 26 #include "NstInpTopRider.hpp" 27 28 namespace Nes 29 { 30 namespace Core 31 { 32 namespace Input 33 { 34 #ifdef NST_MSVC_OPTIMIZE 35 #pragma optimize("s", on) 36 #endif 37 TopRider(const Cpu & c)38 TopRider::TopRider(const Cpu& c) 39 : Device(c,Api::Input::TOPRIDER) 40 { 41 TopRider::Reset(); 42 } 43 Reset()44 void TopRider::Reset() 45 { 46 state[0] = 0; 47 state[1] = 0; 48 stream[0] = 0; 49 stream[1] = 0; 50 strobe = 0; 51 buttons = 0; 52 brake = 0; 53 accel = 0; 54 pos = 0; 55 } 56 SaveState(State::Saver & saver,const byte id) const57 void TopRider::SaveState(State::Saver& saver,const byte id) const 58 { 59 saver.Begin( AsciiId<'T','R'>::R(0,0,id) ).End(); 60 } 61 62 #ifdef NST_MSVC_OPTIMIZE 63 #pragma optimize("", on) 64 #endif 65 BeginFrame(Controllers * const controllers)66 void TopRider::BeginFrame(Controllers* const controllers) 67 { 68 if (controllers) 69 { 70 Controllers::TopRider::callback( controllers->topRider ); 71 72 uint data = controllers->topRider.buttons; 73 74 if ((data & STEERING) == STEERING) 75 data &= STEERING ^ 0xFFU; 76 77 if ( !(data & STEERING) ) pos += (pos > 0 ? -1 : pos < 0 ? +1 : 0); 78 else if ( data & STEER_LEFT ) pos -= (pos > -MAX_STEER); 79 else if ( data & STEER_RIGHT ) pos += (pos < +MAX_STEER); 80 81 if (data & BRAKE) brake += (brake < MAX_BRAKE); 82 else brake -= (brake > 0); 83 84 if (data & ACCEL) accel += (accel < MAX_ACCEL); 85 else accel -= (accel > 0); 86 87 buttons &= (0x80U|0x40U); 88 89 if (data & SHIFT_GEAR) 90 { 91 if (!(buttons & 0x40)) 92 { 93 buttons ^= 0x80; 94 buttons |= 0x40; 95 } 96 } 97 else 98 { 99 buttons &= 0x40U ^ 0xFFU; 100 } 101 102 buttons |= 103 ( 104 (( data & REAR ) >> 5) | 105 (( data & SELECT ) << 3) | 106 (( data & START ) << 1) 107 ); 108 109 data = 0; 110 111 if (pos > 0) 112 { 113 if (pos > DEADZONE_MAX) data = (0x20U | 0x080U); 114 else if (pos > DEADZONE_MID) data = (0x20U | 0x000U); 115 else if (pos > DEADZONE_MIN) data = (0x00U | 0x080U); 116 } 117 else 118 { 119 if (pos < -DEADZONE_MAX) data = (0x40U | 0x100U); 120 else if (pos < -DEADZONE_MID) data = (0x40U | 0x000U); 121 else if (pos < -DEADZONE_MIN) data = (0x00U | 0x100U); 122 } 123 124 state[0] = data | ((buttons & 0x01) << (4+7)) | ((buttons & 0x80) << (4-1)); 125 126 data = 0; 127 128 if (accel > 8 || brake < 8) 129 { 130 if (accel > DEADZONE_MAX) data = 0x008; 131 else if (accel > DEADZONE_MID) data = 0x080; 132 else if (accel > DEADZONE_MIN) data = 0x100; 133 } 134 else 135 { 136 state[0] |= 0x200; 137 138 if (brake > DEADZONE_MAX) data = 0x10; 139 else if (brake > DEADZONE_MID) data = 0x20; 140 else if (brake > DEADZONE_MIN) data = 0x40; 141 } 142 143 state[1] = data | ((buttons & 0x30) << (3+2)); 144 } 145 else 146 { 147 buttons = 0; 148 brake = 0; 149 accel = 0; 150 pos = 0; 151 state[0] = 0; 152 state[1] = 0; 153 } 154 } 155 Poke(uint data)156 void TopRider::Poke(uint data) 157 { 158 const uint prev = strobe; 159 strobe = data & 0x1; 160 161 if (prev > strobe) 162 { 163 stream[0] = state[0]; 164 stream[1] = state[1]; 165 } 166 } 167 Peek(uint port)168 uint TopRider::Peek(uint port) 169 { 170 if (port) 171 { 172 port = (stream[0] & 0x10) | (stream[1] & 0x08); 173 stream[0] >>= 1, stream[1] >>= 1; 174 } 175 176 return port; 177 } 178 } 179 } 180 } 181