[Core/IO] added homemade Master System multitap emulation (BOom)

This commit is contained in:
EkeEke 2014-04-05 00:45:30 +02:00
parent 262a8c7fbc
commit df6dbe855a
8 changed files with 140 additions and 28 deletions

View File

@ -254,6 +254,9 @@ static const rominfo_t game_list[] =
{0xE42E4998, 0, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* Sports Pad Football */
{0x41C948BF, 0, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* Sports Pad Soccer */
/* games requiring homemade multitap */
{0xFAB6F52F, 0, 0, SYSTEM_MS4PLAY, MAPPER_NONE, SYSTEM_SMS2, REGION_USA}, /* BOom */
/* games supporting YM2413 FM */
{0x1C951F8E, 0, 1, SYSTEM_GAMEPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* After Burner */
{0xC13896D5, 0, 1, SYSTEM_GAMEPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* Alex Kidd: The Lost Stars */

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* 3-Buttons & 6-Buttons pad support
* Support for J-CART & 4-Way Play adapters
* 2-Buttons, 3-Buttons & 6-Buttons controller support
* Additional support for J-Cart, 4-Way Play & homemade Master System multitap
*
* Copyright (C) 2007-2011 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2014 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@ -47,7 +47,13 @@ static struct
uint8 Timeout;
} gamepad[MAX_DEVICES];
static uint8 pad_index;
static struct
{
uint8 Latch;
uint8 Counter;
} flipflop[2];
static uint8 latch;
void gamepad_reset(int port)
@ -57,8 +63,12 @@ void gamepad_reset(int port)
gamepad[port].Counter = 0;
gamepad[port].Timeout = 0;
/* reset pad index (4-WayPlay) */
pad_index = 0;
/* reset 4-WayPlay latch */
latch = 0;
/* reset Master System multitap flip-flop */
flipflop[port>>2].Latch = 0;
flipflop[port>>2].Counter = 0;
}
void gamepad_refresh(int port)
@ -192,13 +202,15 @@ void gamepad_2_write(unsigned char data, unsigned char mask)
unsigned char wayplay_1_read(void)
{
if (pad_index < 4)
/* check if TH on port B is HIGH */
if (latch & 0x04)
{
return gamepad_read(pad_index);
/* 4-WayPlay detection : xxxxx00 */
return 0x7c;
}
/* multitap detection */
return 0x70;
/* TR & TL on port B select controller # (0-3) */
return gamepad_read(latch);
}
unsigned char wayplay_2_read(void)
@ -208,18 +220,14 @@ unsigned char wayplay_2_read(void)
void wayplay_1_write(unsigned char data, unsigned char mask)
{
if (pad_index < 4)
{
gamepad_write(pad_index, data, mask);
}
/* TR & TL on port B select controller # (0-3) */
gamepad_write(latch & 0x03, data, mask);
}
void wayplay_2_write(unsigned char data, unsigned char mask)
{
if ((mask & 0x70) == 0x70)
{
pad_index = (data & 0x70) >> 4;
}
/* latch TH, TR & TL state on port B */
latch = ((data & mask) >> 4) & 0x07;
}
@ -239,3 +247,48 @@ void jcart_write(unsigned int address, unsigned int data)
gamepad_write(6, (data & 1) << 6, 0x40);
return;
}
/*--------------------------------------------------------------------------*/
/* Master System multitap ports handler (original design by Furrtek) */
/* cf. http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png */
/*--------------------------------------------------------------------------*/
unsigned char ms4play_1_read(void)
{
return gamepad_read(flipflop[0].Counter);
}
unsigned char ms4play_2_read(void)
{
return gamepad_read(flipflop[1].Counter + 4);
}
void ms4play_1_write(unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (flipflop[0].Latch & ~mask) | (data & mask);
/* check TH 1->0 transitions */
if ((flipflop[0].Latch & 0x40) && !(data & 0x40))
{
flipflop[0].Counter = (flipflop[0].Counter + 1) & 0x03;
}
/* update internal state */
flipflop[0].Latch = data;
}
void ms4play_2_write(unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (flipflop[1].Latch & ~mask) | (data & mask);
/* check TH=1 to TH=0 transition */
if ((flipflop[1].Latch & 0x40) && !(data & 0x40))
{
flipflop[1].Counter = (flipflop[1].Counter + 1) & 0x03;
}
/* update internal state */
flipflop[1].Latch = data;
}

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* 3-Buttons & 6-Buttons pad support
* Support for J-CART & 4-Way Play adapters
* 2-Buttons, 3-Buttons & 6-Buttons controller support
* Additional support for J-Cart, 4-Way Play & homemade Master System multitap
*
* Copyright (C) 2007-2011 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2014 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
@ -53,5 +53,9 @@ extern void wayplay_1_write(unsigned char data, unsigned char mask);
extern void wayplay_2_write(unsigned char data, unsigned char mask);
extern unsigned int jcart_read(unsigned int address);
extern void jcart_write(unsigned int address, unsigned int data);
extern unsigned char ms4play_1_read(void);
extern unsigned char ms4play_2_read(void);
extern void ms4play_1_write(unsigned char data, unsigned char mask);
extern void ms4play_2_write(unsigned char data, unsigned char mask);
#endif

View File

@ -170,6 +170,19 @@ void input_init(void)
break;
}
case SYSTEM_MS4PLAY:
{
for (i=0; i<4; i++)
{
if (player < MAX_INPUTS)
{
input.dev[i] = DEVICE_PAD2B;
player++;
}
}
break;
}
case SYSTEM_LIGHTPHASER:
{
input.dev[0] = DEVICE_LIGHTGUN;
@ -276,6 +289,19 @@ void input_init(void)
break;
}
case SYSTEM_MS4PLAY:
{
for (i=4; i<8; i++)
{
if (player < MAX_INPUTS)
{
input.dev[i] = DEVICE_PAD2B;
player++;
}
}
break;
}
case SYSTEM_LIGHTPHASER:
{
input.dev[4] = DEVICE_LIGHTGUN;

View File

@ -51,12 +51,12 @@
#define SYSTEM_JUSTIFIER (4) /* Konami Justifiers (port B only) */
#define SYSTEM_XE_A1P (5) /* XE-A1P analog controller (port A only) */
#define SYSTEM_ACTIVATOR (6) /* Sega Activator */
#define SYSTEM_MS_GAMEPAD (7) /* single 2-buttons Control Pad (Master System) */
#define SYSTEM_LIGHTPHASER (7) /* Sega Light Phaser (Master System) */
#define SYSTEM_PADDLE (8) /* Sega Paddle Control (Master System) */
#define SYSTEM_SPORTSPAD (9) /* Sega Sports Pad (Master System) */
#define SYSTEM_TEAMPLAYER (10) /* Multi Tap -- Sega TeamPlayer */
#define SYSTEM_WAYPLAY (11) /* Multi Tap -- EA 4-Way Play (use both ports) */
#define SYSTEM_MS4PLAY (10) /* Multi Tap -- Master System homemade */
#define SYSTEM_TEAMPLAYER (11) /* Multi Tap -- Sega TeamPlayer */
#define SYSTEM_WAYPLAY (12) /* Multi Tap -- EA 4-Way Play (use both ports) */
/* Device type */
#define NO_DEVICE (0xff) /* unconnected device (fixed ID for Team Player) */

View File

@ -122,6 +122,13 @@ void io_init(void)
break;
}
case SYSTEM_MS4PLAY:
{
port[0].data_w = ms4play_1_write;
port[0].data_r = ms4play_1_read;
break;
}
case SYSTEM_LIGHTPHASER:
{
port[0].data_w = dummy_write;
@ -209,6 +216,13 @@ void io_init(void)
break;
}
case SYSTEM_MS4PLAY:
{
port[1].data_w = ms4play_2_write;
port[1].data_r = ms4play_2_read;
break;
}
case SYSTEM_LIGHTPHASER:
{
port[1].data_w = dummy_write;

View File

@ -108,6 +108,7 @@ extern const u8 Ctrl_paddle_png[];
extern const u8 Ctrl_sportspad_png[];
extern const u8 Ctrl_none_png[];
extern const u8 Ctrl_teamplayer_png[];
extern const u8 Ctrl_ms4play_png[];
extern const u8 Ctrl_pad_auto_png[];
extern const u8 Ctrl_pad2b_png[];
extern const u8 Ctrl_pad3b_png[];
@ -2028,7 +2029,7 @@ static void ctrlmenu(void)
u32 exp, index = 0;
/* System devices */
gui_item items_sys[2][12] =
gui_item items_sys[2][13] =
{
{
{NULL,Ctrl_none_png ,"","Select Port 1 device",110,130,48,72},
@ -2041,6 +2042,7 @@ static void ctrlmenu(void)
{NULL,Ctrl_lightphaser_png,"","Select Port 1 device", 89,109,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 1 device", 86,117,96,84},
{NULL,Ctrl_sportspad_png ,"","Select Port 1 device", 95,117,76,84},
{NULL,Ctrl_ms4play_png ,"","Select Port 1 device", 94,100,80,100},
{NULL,Ctrl_teamplayer_png ,"","Select Port 1 device", 94,109,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 1 device", 98,110,72,92}
},
@ -2055,6 +2057,7 @@ static void ctrlmenu(void)
{NULL,Ctrl_lightphaser_png,"","Select Port 2 device", 89,279,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 2 device", 86,287,96,84},
{NULL,Ctrl_sportspad_png ,"","Select Port 2 device", 95,287,76,84},
{NULL,Ctrl_ms4play_png ,"","Select Port 1 device", 94,270,80,100},
{NULL,Ctrl_teamplayer_png ,"","Select Port 2 device", 94,279,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 2 device", 98,280,72,92}
}
@ -2121,7 +2124,7 @@ static void ctrlmenu(void)
button_player_none_data.texture[0] = gxTextureOpenPNG(button_player_none_data.image[0],0);
/* initialize custom images */
for (i=0; i<12; i++)
for (i=0; i<13; i++)
{
items_sys[1][i].texture = items_sys[0][i].texture = gxTextureOpenPNG(items_sys[0][i].data,0);
}
@ -2415,8 +2418,17 @@ static void ctrlmenu(void)
case DEVICE_PAD3B:
case DEVICE_PAD6B:
{
items = items_special[0];
special = &config.input[player].padtype;
if (input.system[index/4] == SYSTEM_MS4PLAY)
{
/* force 2-buttons pad */
items = items_special[3];
special = NULL;
}
else
{
items = items_special[0];
special = &config.input[player].padtype;
}
break;
}

BIN
gx/images/Ctrl_ms4play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB