/***************************************************************************************1* Genesis Plus2* Sega Sports Pad support3*4* Copyright (C) 2007-2013 Eke-Eke (Genesis Plus GX)5*6* Redistribution and use of this code or any derivative works are permitted7* provided that the following conditions are met:8*9* - Redistributions may not be sold, nor may they be used in a commercial10* product or activity.11*12* - Redistributions that are modified from the original source must include the13* complete source code, including the source code for all components used by a14* binary built from the modified sources. However, as a special exception, the15* source code distributed need not include anything that is normally distributed16* (in either source or binary form) with the major components (compiler, kernel,17* and so on) of the operating system on which the executable runs, unless that18* component itself accompanies the executable.19*20* - Redistributions must reproduce the above copyright notice, this list of21* conditions and the following disclaimer in the documentation and/or other22* materials provided with the distribution.23*24* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"25* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE26* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE27* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE28* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR29* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF30* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS31* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN32* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)33* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE34* POSSIBILITY OF SUCH DAMAGE.35*36****************************************************************************************/3738#include "shared.h"3940struct41{42uint8 State;43uint8 Counter;44} sportspad[2];4546void sportspad_reset(int index)47{48input.analog[index][0] = 128;49input.analog[index][1] = 128;50sportspad[index>>2].State = 0x40;51sportspad[index>>2].Counter = 0;52}5354INLINE unsigned char sportspad_read(int port)55{56/* Buttons 1(B) & 2(C) status (active low) */57unsigned char temp = ~(input.pad[port] & 0x30);5859/* Pad index */60int index = port >> 2;6162/* Clear low bits */63temp &= 0x70;6465/* Detect current state */66switch (sportspad[index].Counter & 3)67{68case 1:69{70/* X position high bits */71temp |= (input.analog[port][0] >> 4) & 0x0F;72break;73}7475case 2:76{77/* X position low bits */78temp |= input.analog[port][0] & 0x0F;79break;80}8182case 3:83{84/* Y position high bits */85temp |= (input.analog[port][1] >> 4) & 0x0F;86break;87}8889default:90{91/* Y position low bits */92temp |= input.analog[port][1] & 0x0F;93break;94}95}9697return temp;98}99100INLINE void sportspad_write(int index, unsigned char data, unsigned char mask)101{102/* update bits set as output only */103data = (sportspad[index].State & ~mask) | (data & mask);104105/* check TH transitions */106if ((data ^ sportspad[index].State) & 0x40)107{108sportspad[index].Counter++;109}110111/* update internal state */112sportspad[index].State = data;113}114115unsigned char sportspad_1_read(void)116{117return sportspad_read(0);118}119120unsigned char sportspad_2_read(void)121{122return sportspad_read(4);123}124125void sportspad_1_write(unsigned char data, unsigned char mask)126{127sportspad_write(0, data, mask);128}129130void sportspad_2_write(unsigned char data, unsigned char mask)131{132sportspad_write(1, data, mask);133}134135136