/***************************************************************************************1* Genesis Plus2* 3-Buttons & 6-Buttons pad support3* Support for J-CART & 4-Way Play adapters4*5* Copyright (C) 2007-2011 Eke-Eke (Genesis Plus GX)6*7* Redistribution and use of this code or any derivative works are permitted8* provided that the following conditions are met:9*10* - Redistributions may not be sold, nor may they be used in a commercial11* product or activity.12*13* - Redistributions that are modified from the original source must include the14* complete source code, including the source code for all components used by a15* binary built from the modified sources. However, as a special exception, the16* source code distributed need not include anything that is normally distributed17* (in either source or binary form) with the major components (compiler, kernel,18* and so on) of the operating system on which the executable runs, unless that19* component itself accompanies the executable.20*21* - Redistributions must reproduce the above copyright notice, this list of22* conditions and the following disclaimer in the documentation and/or other23* materials provided with the distribution.24*25* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"26* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE27* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE28* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE29* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR30* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF31* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS32* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN33* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)34* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE35* POSSIBILITY OF SUCH DAMAGE.36*37****************************************************************************************/3839#include "shared.h"40#include "gamepad.h"4142uint8 pad_index;434445void gamepad_reset(int port)46{47/* default state (Gouketsuji Ichizoku / Power Instinct, Samurai Spirits / Samurai Shodown) */48gamepad[port].State = 0x40;49gamepad[port].Counter = 0;50gamepad[port].Timeout = 0;5152/* reset pad index (4-WayPlay) */53pad_index = 0;54}5556void gamepad_refresh(int port)57{58/* 6-buttons pad */59if (gamepad[port].Timeout++ > 25)60{61gamepad[port].Counter = 0;62gamepad[port].Timeout = 0;63}64}6566INLINE unsigned char gamepad_read(int port)67{68/* bit 7 is latched, returns current TH state */69unsigned int data = (gamepad[port].State & 0x40) | 0x3F;7071/* pad value */72unsigned int val = input.pad[port];7374/* get current step (TH state) */75unsigned int step = gamepad[port].Counter | ((data >> 6) & 1);7677switch (step)78{79case 1: /*** First High ***/80case 3: /*** Second High ***/81case 5: /*** Third High ***/82{83/* TH = 1 : ?1CBRLDU */84data &= ~(val & 0x3F);85break;86}8788case 0: /*** First low ***/89case 2: /*** Second low ***/90{91/* TH = 0 : ?0SA00DU */92data &= ~(val & 0x03);93data &= ~((val >> 2) & 0x30);94data &= ~0x0C;95break;96}9798/* 6buttons specific (taken from gen-hw.txt) */99/* A 6-button gamepad allows the extra buttons to be read based on how */100/* many times TH is switched from 1 to 0 (and not 0 to 1). Observe the */101/* following sequence */102/*103TH = 1 : ?1CBRLDU 3-button pad return value104TH = 0 : ?0SA00DU 3-button pad return value105TH = 1 : ?1CBRLDU 3-button pad return value106TH = 0 : ?0SA0000 D3-0 are forced to '0'107TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0108TH = 0 : ?0SA1111 D3-0 are forced to '1'109*/110case 4: /*** Third Low ***/111{112/* TH = 0 : ?0SA0000 D3-0 are forced to '0'*/113data &= ~((val >> 2) & 0x30);114data &= ~0x0F;115break;116}117118case 6: /*** Fourth Low ***/119{120/* TH = 0 : ?0SA1111 D3-0 are forced to '1'*/121data &= ~((val >> 2) & 0x30);122break;123}124125case 7: /*** Fourth High ***/126{127/* TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0*/128data &= ~(val & 0x30);129data &= ~((val >> 8) & 0x0F);130break;131}132}133134return data;135}136137INLINE void gamepad_write(int port, unsigned char data, unsigned char mask)138{139/* update bits set as output only */140data = (gamepad[port].State & ~mask) | (data & mask);141142if (input.dev[port] == DEVICE_PAD6B)143{144/* TH=0 to TH=1 transition */145if (!(gamepad[port].State & 0x40) && (data & 0x40))146{147gamepad[port].Counter = (gamepad[port].Counter + 2) & 6;148gamepad[port].Timeout = 0;149}150}151152/* update internal state */153gamepad[port].State = data;154}155156157/*--------------------------------------------------------------------------*/158/* Default ports handlers */159/*--------------------------------------------------------------------------*/160161unsigned char gamepad_1_read(void)162{163return gamepad_read(0);164}165166unsigned char gamepad_2_read(void)167{168return gamepad_read(4);169}170171void gamepad_1_write(unsigned char data, unsigned char mask)172{173gamepad_write(0, data, mask);174}175176void gamepad_2_write(unsigned char data, unsigned char mask)177{178gamepad_write(4, data, mask);179}180181/*--------------------------------------------------------------------------*/182/* 4-WayPlay ports handler */183/*--------------------------------------------------------------------------*/184185unsigned char wayplay_1_read(void)186{187if (pad_index < 4)188{189return gamepad_read(pad_index);190}191192/* multitap detection */193return 0x70;194}195196unsigned char wayplay_2_read(void)197{198return 0x7F;199}200201void wayplay_1_write(unsigned char data, unsigned char mask)202{203if (pad_index < 4)204{205gamepad_write(pad_index, data, mask);206}207}208209void wayplay_2_write(unsigned char data, unsigned char mask)210{211if ((mask & 0x70) == 0x70)212{213pad_index = (data & 0x70) >> 4;214}215}216217218/*--------------------------------------------------------------------------*/219/* J-Cart memory handlers */220/*--------------------------------------------------------------------------*/221222unsigned int jcart_read(unsigned int address)223{224/* TH2 output read is fixed to zero (fixes Micro Machines 2) */225return ((gamepad_read(5) & 0x7F) | ((gamepad_read(6) & 0x3F) << 8));226}227228void jcart_write(unsigned int address, unsigned int data)229{230gamepad_write(5, (data & 1) << 6, 0x40);231gamepad_write(6, (data & 1) << 6, 0x40);232return;233}234235236