2008-08-07 14:26:07 +02:00
|
|
|
/***************************************************************************************
|
2009-05-13 16:26:55 +02:00
|
|
|
* Genesis Plus
|
2008-08-07 14:26:07 +02:00
|
|
|
* I/O Chip
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
2009-05-13 16:26:55 +02:00
|
|
|
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
|
2008-08-07 14:26:07 +02:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
****************************************************************************************/
|
|
|
|
|
|
|
|
#include "shared.h"
|
|
|
|
|
|
|
|
uint8 io_reg[0x10];
|
|
|
|
uint8 region_code = REGION_USA;
|
|
|
|
|
2009-08-06 20:31:05 +02:00
|
|
|
static struct port_t
|
2008-08-07 14:26:07 +02:00
|
|
|
{
|
2010-07-16 10:30:25 +02:00
|
|
|
void (*data_w)(unsigned int data);
|
|
|
|
unsigned int (*data_r)(void);
|
2008-08-07 14:26:07 +02:00
|
|
|
} port[3];
|
|
|
|
|
2010-07-16 10:30:25 +02:00
|
|
|
static void dummy_write(unsigned int data)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int dummy_read(void)
|
|
|
|
{
|
|
|
|
return 0x7F;
|
|
|
|
}
|
|
|
|
|
2009-08-06 20:31:05 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* I/O chip functions *
|
|
|
|
* *
|
|
|
|
*****************************************************************************/
|
|
|
|
void io_init(void)
|
2008-08-07 14:26:07 +02:00
|
|
|
{
|
2009-12-13 20:09:15 +01:00
|
|
|
/* Initialize IO Ports handlers */
|
2008-08-07 14:26:07 +02:00
|
|
|
switch (input.system[0])
|
|
|
|
{
|
|
|
|
case SYSTEM_GAMEPAD:
|
|
|
|
port[0].data_w = gamepad_1_write;
|
|
|
|
port[0].data_r = gamepad_1_read;
|
|
|
|
break;
|
|
|
|
|
2008-08-10 22:40:04 +02:00
|
|
|
case SYSTEM_MOUSE:
|
|
|
|
port[0].data_w = mouse_write;
|
|
|
|
port[0].data_r = mouse_read;
|
|
|
|
break;
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
case SYSTEM_WAYPLAY:
|
2008-12-10 19:16:30 +01:00
|
|
|
port[0].data_w = wayplay_1_write;
|
|
|
|
port[0].data_r = wayplay_1_read;
|
|
|
|
break;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
|
|
|
case SYSTEM_TEAMPLAYER:
|
2008-12-10 19:16:30 +01:00
|
|
|
port[0].data_w = teamplayer_1_write;
|
|
|
|
port[0].data_r = teamplayer_1_read;
|
|
|
|
break;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
default:
|
2010-07-16 10:30:25 +02:00
|
|
|
port[0].data_w = dummy_write;
|
|
|
|
port[0].data_r = dummy_read;
|
2008-08-07 14:26:07 +02:00
|
|
|
break;
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
|
|
|
|
switch (input.system[1])
|
|
|
|
{
|
|
|
|
case SYSTEM_GAMEPAD:
|
|
|
|
port[1].data_w = gamepad_2_write;
|
|
|
|
port[1].data_r = gamepad_2_read;
|
|
|
|
break;
|
|
|
|
|
2008-08-11 17:18:57 +02:00
|
|
|
case SYSTEM_MOUSE:
|
|
|
|
port[1].data_w = mouse_write;
|
|
|
|
port[1].data_r = mouse_read;
|
|
|
|
break;
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
case SYSTEM_MENACER:
|
2010-07-16 10:30:25 +02:00
|
|
|
port[1].data_w = dummy_write;
|
2008-08-07 14:26:07 +02:00
|
|
|
port[1].data_r = menacer_read;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SYSTEM_JUSTIFIER:
|
2010-07-16 10:30:25 +02:00
|
|
|
port[1].data_w = dummy_write;
|
2008-08-07 14:26:07 +02:00
|
|
|
port[1].data_r = justifier_read;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SYSTEM_WAYPLAY:
|
2008-12-10 19:16:30 +01:00
|
|
|
port[1].data_w = wayplay_2_write;
|
|
|
|
port[1].data_r = wayplay_2_read;
|
|
|
|
break;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
|
|
|
case SYSTEM_TEAMPLAYER:
|
2008-12-10 19:16:30 +01:00
|
|
|
port[1].data_w = teamplayer_2_write;
|
|
|
|
port[1].data_r = teamplayer_2_read;
|
|
|
|
break;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
default:
|
2010-07-16 10:30:25 +02:00
|
|
|
port[1].data_w = dummy_write;
|
|
|
|
port[1].data_r = dummy_read;
|
2008-08-07 14:26:07 +02:00
|
|
|
break;
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
|
|
|
|
/* External Port (unconnected) */
|
2010-07-16 10:30:25 +02:00
|
|
|
port[2].data_w = dummy_write;
|
|
|
|
port[2].data_r = dummy_read;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2009-12-13 20:09:15 +01:00
|
|
|
/* Initialize connected input devices */
|
2009-08-06 20:31:05 +02:00
|
|
|
input_init();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void io_reset(void)
|
|
|
|
{
|
|
|
|
/* Reset I/O registers */
|
2010-06-14 10:05:45 +02:00
|
|
|
io_reg[0x00] = region_code | 0x20 | (config.tmss & 1);
|
2010-07-16 10:30:25 +02:00
|
|
|
io_reg[0x01] = 0x00;
|
|
|
|
io_reg[0x02] = 0x00;
|
|
|
|
io_reg[0x03] = 0x00;
|
2010-05-28 14:08:00 +02:00
|
|
|
io_reg[0x04] = 0x00;
|
|
|
|
io_reg[0x05] = 0x00;
|
|
|
|
io_reg[0x06] = 0x00;
|
|
|
|
io_reg[0x07] = 0xFF;
|
|
|
|
io_reg[0x08] = 0x00;
|
|
|
|
io_reg[0x09] = 0x00;
|
|
|
|
io_reg[0x0A] = 0xFF;
|
|
|
|
io_reg[0x0B] = 0x00;
|
|
|
|
io_reg[0x0C] = 0x00;
|
|
|
|
io_reg[0x0D] = 0xFB;
|
|
|
|
io_reg[0x0E] = 0x00;
|
|
|
|
io_reg[0x0F] = 0x00;
|
|
|
|
|
2009-12-13 20:09:15 +01:00
|
|
|
/* Reset connected input devices */
|
2008-08-07 14:26:07 +02:00
|
|
|
input_reset();
|
|
|
|
}
|
|
|
|
|
2010-07-16 10:30:25 +02:00
|
|
|
void io_write(unsigned int offset, unsigned int data)
|
2008-08-07 14:26:07 +02:00
|
|
|
{
|
|
|
|
switch (offset)
|
|
|
|
{
|
|
|
|
case 0x01: /* Port A Data */
|
|
|
|
case 0x02: /* Port B Data */
|
|
|
|
case 0x03: /* Port C Data */
|
2010-07-16 10:30:25 +02:00
|
|
|
io_reg[offset] = data;
|
|
|
|
port[offset-1].data_w(data);
|
2008-08-07 14:26:07 +02:00
|
|
|
return;
|
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
case 0x04: /* Port A Ctrl */
|
2010-05-28 14:08:00 +02:00
|
|
|
case 0x05: /* Port B Ctrl */
|
2008-12-10 19:16:30 +01:00
|
|
|
case 0x06: /* Port C Ctrl */
|
2010-07-16 10:30:25 +02:00
|
|
|
if (data != io_reg[offset])
|
|
|
|
{
|
|
|
|
io_reg[offset] = data;
|
|
|
|
port[offset-4].data_w(io_reg[offset-3]);
|
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
return;
|
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
case 0x07: /* Port A TxData */
|
|
|
|
case 0x0A: /* Port B TxData */
|
|
|
|
case 0x0D: /* Port C TxData */
|
2010-07-16 10:30:25 +02:00
|
|
|
io_reg[offset] = data;
|
2008-08-07 14:26:07 +02:00
|
|
|
return;
|
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
case 0x09: /* Port A S-Ctrl */
|
|
|
|
case 0x0C: /* Port B S-Ctrl */
|
|
|
|
case 0x0F: /* Port C S-Ctrl */
|
2010-07-16 10:30:25 +02:00
|
|
|
io_reg[offset] = data & 0xF8;
|
2010-05-28 14:08:00 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
default: /* Read-only ports */
|
2008-08-07 14:26:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2008-12-10 19:16:30 +01:00
|
|
|
|
2010-07-16 10:30:25 +02:00
|
|
|
unsigned int io_read(unsigned int offset)
|
2008-08-07 14:26:07 +02:00
|
|
|
{
|
|
|
|
switch(offset)
|
|
|
|
{
|
|
|
|
case 0x01: /* Port A Data */
|
|
|
|
case 0x02: /* Port B Data */
|
2008-12-10 19:16:30 +01:00
|
|
|
case 0x03: /* Port C Data */
|
|
|
|
{
|
2010-07-16 10:30:25 +02:00
|
|
|
unsigned int mask = 0x80 | io_reg[offset + 3];
|
|
|
|
unsigned int data = port[offset-1].data_r();
|
|
|
|
return (io_reg[offset] & mask) | (data & ~mask);
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2010-05-28 14:08:00 +02:00
|
|
|
default: /* return register value */
|
2010-07-16 10:30:25 +02:00
|
|
|
return io_reg[offset];
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
}
|