Genesis-Plus-GX/source/gen_io.c

295 lines
8.5 KiB
C
Raw Normal View History

2008-08-07 14:26:07 +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)
* 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;
int old_system[2] = {-1,-1};
2008-08-07 14:26:07 +02:00
static struct port_t
2008-08-07 14:26:07 +02:00
{
2008-12-10 19:16:30 +01:00
void (*data_w)(uint32 data);
uint32 (*data_r)(void);
2008-08-07 14:26:07 +02:00
} port[3];
/*****************************************************************************
* I/O chip functions *
* *
*****************************************************************************/
void io_init(void)
2008-08-07 14:26:07 +02:00
{
/* restore previous setting */
if (old_system[0] != -1) input.system[0] = old_system[0];
if (old_system[1] != -1) input.system[1] = old_system[1];
/* initialize default GUN settings */
input.x_offset = 0x00;
input.y_offset = 0x00;
/**********************************************
SEGA MENACER
***********************************************/
if (strstr(rominfo.international,"MENACER") != NULL)
2008-08-07 14:26:07 +02:00
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
input.system[0] = NO_SYSTEM;
input.system[1] = SYSTEM_MENACER;
input.x_offset = 0x52;
input.y_offset = 0x00;
}
else if (strstr(rominfo.international,"T2 ; THE ARCADE GAME") != NULL)
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_MENACER;
input.x_offset = 0x84;
input.y_offset = 0x08;
}
else if (strstr(rominfo.international,"BODY COUNT") != NULL)
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
input.system[0] = SYSTEM_MOUSE;
input.system[1] = SYSTEM_MENACER;
input.x_offset = 0x44;
input.y_offset = 0x18;
}
2008-08-07 14:26:07 +02:00
/**********************************************
KONAMI JUSTIFIER
***********************************************/
else if (strstr(rominfo.international,"LETHAL ENFORCERSII") != NULL)
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_JUSTIFIER;
input.x_offset = 0x18;
input.y_offset = 0x00;
}
else if (strstr(rominfo.international,"LETHAL ENFORCERS") != NULL)
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_JUSTIFIER;
input.x_offset = 0x00;
input.y_offset = 0x00;
}
/**********************************************
J-CART
***********************************************/
if (cart.hw.jcart)
{
/* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0];
if (old_system[1] == -1) old_system[1] = input.system[1];
/* set default settings */
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
}
2008-08-07 14:26:07 +02:00
/**********************************************
Initialize IO Port 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;
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:
2008-08-07 14:26:07 +02:00
port[0].data_w = NULL;
port[0].data_r = NULL;
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:
port[1].data_w = NULL;
port[1].data_r = menacer_read;
break;
case SYSTEM_JUSTIFIER:
port[1].data_w = NULL;
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:
2008-08-07 14:26:07 +02:00
port[1].data_w = NULL;
port[1].data_r = NULL;
break;
2008-12-10 19:16:30 +01:00
}
2008-08-07 14:26:07 +02:00
/* External Port (unconnected) */
port[2].data_w = NULL;
port[2].data_r = NULL;
/* Initialize Input Devices */
input_init();
}
void io_reset(void)
{
/* I/O register default settings */
uint8 io_def[0x10] =
{
0xA0,
0x7F, 0x7F, 0x7F,
0x00, 0x00, 0x00,
0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00,
0xFB, 0x00, 0x00,
};
/* Reset I/O registers */
memcpy (io_reg, io_def, 0x10);
/* Reset Input Devices */
2008-08-07 14:26:07 +02:00
input_reset();
}
2008-12-10 19:16:30 +01:00
void io_write(uint32 offset, uint32 value)
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 */
io_reg[offset] = ((value & 0x80) | (value & io_reg[offset+3]));
if(port[offset-1].data_w) port[offset-1].data_w(value);
return;
2008-12-10 19:16:30 +01:00
case 0x05: /* Port B Ctrl */
2008-08-07 14:26:07 +02:00
if (((value & 0x7F) == 0x7F) &&
((input.system[0] == SYSTEM_TEAMPLAYER) ||
(input.system[1] == SYSTEM_TEAMPLAYER)))
{
/* autodetect 4-Way play ! */
input.system[0] = SYSTEM_WAYPLAY;
input.system[1] = SYSTEM_WAYPLAY;
port[0].data_w = wayplay_1_write;
port[0].data_r = wayplay_1_read;
port[1].data_w = wayplay_2_write;
port[1].data_r = wayplay_2_read;
input_reset();
}
2008-12-10 19:16:30 +01:00
case 0x04: /* Port A Ctrl */
case 0x06: /* Port C Ctrl */
2008-08-07 14:26:07 +02:00
io_reg[offset] = value & 0xFF;
io_reg[offset-3] = ((io_reg[offset-3] & 0x80) | (io_reg[offset-3] & io_reg[offset]));
return;
2008-12-10 19:16:30 +01:00
case 0x07: /* Port A TxData */
case 0x0A: /* Port B TxData */
case 0x0D: /* Port C TxData */
2008-08-07 14:26:07 +02:00
io_reg[offset] = value;
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 */
2008-08-07 14:26:07 +02:00
io_reg[offset] = (value & 0xF8);
return;
}
}
2008-12-10 19:16:30 +01:00
uint32 io_read(uint32 offset)
2008-08-07 14:26:07 +02:00
{
switch(offset)
{
case 0x00: /* Version register */
2008-12-10 19:16:30 +01:00
{
uint8 has_scd = 0x20; /* No Sega CD unit attached */
uint8 gen_ver = (config.bios_enabled == 3) ? 0x01 : 0x00; /* hardware version */
2008-08-07 14:26:07 +02:00
return (region_code | has_scd | gen_ver);
2008-12-10 19:16:30 +01:00
}
2008-08-07 14:26:07 +02:00
case 0x01: /* Port A Data */
case 0x02: /* Port B Data */
2008-12-10 19:16:30 +01:00
case 0x03: /* Port C Data */
{
uint8 input = 0x7F; /* default input state */
2008-08-07 14:26:07 +02:00
if(port[offset-1].data_r) input = port[offset-1].data_r();
2008-12-10 19:16:30 +01:00
return (io_reg[offset] | ((~io_reg[offset+3]) & input));
}
2008-08-07 14:26:07 +02:00
2008-12-10 19:16:30 +01:00
default:
return (io_reg[offset]);
}
2008-08-07 14:26:07 +02:00
}