[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 */ {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 */ {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 */ /* games supporting YM2413 FM */
{0x1C951F8E, 0, 1, SYSTEM_GAMEPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* After Burner */ {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 */ {0xC13896D5, 0, 1, SYSTEM_GAMEPAD, MAPPER_SEGA, SYSTEM_SMS2, REGION_USA}, /* Alex Kidd: The Lost Stars */

View File

@ -1,9 +1,9 @@
/*************************************************************************************** /***************************************************************************************
* Genesis Plus * Genesis Plus
* 3-Buttons & 6-Buttons pad support * 2-Buttons, 3-Buttons & 6-Buttons controller support
* Support for J-CART & 4-Way Play adapters * 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 * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * provided that the following conditions are met:
@ -47,7 +47,13 @@ static struct
uint8 Timeout; uint8 Timeout;
} gamepad[MAX_DEVICES]; } gamepad[MAX_DEVICES];
static uint8 pad_index; static struct
{
uint8 Latch;
uint8 Counter;
} flipflop[2];
static uint8 latch;
void gamepad_reset(int port) void gamepad_reset(int port)
@ -57,8 +63,12 @@ void gamepad_reset(int port)
gamepad[port].Counter = 0; gamepad[port].Counter = 0;
gamepad[port].Timeout = 0; gamepad[port].Timeout = 0;
/* reset pad index (4-WayPlay) */ /* reset 4-WayPlay latch */
pad_index = 0; latch = 0;
/* reset Master System multitap flip-flop */
flipflop[port>>2].Latch = 0;
flipflop[port>>2].Counter = 0;
} }
void gamepad_refresh(int port) 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) 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 */ /* TR & TL on port B select controller # (0-3) */
return 0x70; return gamepad_read(latch);
} }
unsigned char wayplay_2_read(void) 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) void wayplay_1_write(unsigned char data, unsigned char mask)
{ {
if (pad_index < 4) /* TR & TL on port B select controller # (0-3) */
{ gamepad_write(latch & 0x03, data, mask);
gamepad_write(pad_index, data, mask);
}
} }
void wayplay_2_write(unsigned char data, unsigned char mask) void wayplay_2_write(unsigned char data, unsigned char mask)
{ {
if ((mask & 0x70) == 0x70) /* latch TH, TR & TL state on port B */
{ latch = ((data & mask) >> 4) & 0x07;
pad_index = (data & 0x70) >> 4;
}
} }
@ -239,3 +247,48 @@ void jcart_write(unsigned int address, unsigned int data)
gamepad_write(6, (data & 1) << 6, 0x40); gamepad_write(6, (data & 1) << 6, 0x40);
return; 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 * Genesis Plus
* 3-Buttons & 6-Buttons pad support * 2-Buttons, 3-Buttons & 6-Buttons controller support
* Support for J-CART & 4-Way Play adapters * 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 * Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met: * 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 void wayplay_2_write(unsigned char data, unsigned char mask);
extern unsigned int jcart_read(unsigned int address); extern unsigned int jcart_read(unsigned int address);
extern void jcart_write(unsigned int address, unsigned int data); 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 #endif

View File

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

View File

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

View File

@ -122,6 +122,13 @@ void io_init(void)
break; break;
} }
case SYSTEM_MS4PLAY:
{
port[0].data_w = ms4play_1_write;
port[0].data_r = ms4play_1_read;
break;
}
case SYSTEM_LIGHTPHASER: case SYSTEM_LIGHTPHASER:
{ {
port[0].data_w = dummy_write; port[0].data_w = dummy_write;
@ -209,6 +216,13 @@ void io_init(void)
break; break;
} }
case SYSTEM_MS4PLAY:
{
port[1].data_w = ms4play_2_write;
port[1].data_r = ms4play_2_read;
break;
}
case SYSTEM_LIGHTPHASER: case SYSTEM_LIGHTPHASER:
{ {
port[1].data_w = dummy_write; 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_sportspad_png[];
extern const u8 Ctrl_none_png[]; extern const u8 Ctrl_none_png[];
extern const u8 Ctrl_teamplayer_png[]; extern const u8 Ctrl_teamplayer_png[];
extern const u8 Ctrl_ms4play_png[];
extern const u8 Ctrl_pad_auto_png[]; extern const u8 Ctrl_pad_auto_png[];
extern const u8 Ctrl_pad2b_png[]; extern const u8 Ctrl_pad2b_png[];
extern const u8 Ctrl_pad3b_png[]; extern const u8 Ctrl_pad3b_png[];
@ -2028,7 +2029,7 @@ static void ctrlmenu(void)
u32 exp, index = 0; u32 exp, index = 0;
/* System devices */ /* 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}, {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_lightphaser_png,"","Select Port 1 device", 89,109,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 1 device", 86,117,96,84}, {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_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_teamplayer_png ,"","Select Port 1 device", 94,109,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 1 device", 98,110,72,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_lightphaser_png,"","Select Port 2 device", 89,279,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 2 device", 86,287,96,84}, {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_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_teamplayer_png ,"","Select Port 2 device", 94,279,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 2 device", 98,280,72,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); button_player_none_data.texture[0] = gxTextureOpenPNG(button_player_none_data.image[0],0);
/* initialize custom images */ /* 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); items_sys[1][i].texture = items_sys[0][i].texture = gxTextureOpenPNG(items_sys[0][i].data,0);
} }
@ -2414,9 +2417,18 @@ static void ctrlmenu(void)
case DEVICE_PAD2B: case DEVICE_PAD2B:
case DEVICE_PAD3B: case DEVICE_PAD3B:
case DEVICE_PAD6B: case DEVICE_PAD6B:
{
if (input.system[index/4] == SYSTEM_MS4PLAY)
{
/* force 2-buttons pad */
items = items_special[3];
special = NULL;
}
else
{ {
items = items_special[0]; items = items_special[0];
special = &config.input[player].padtype; special = &config.input[player].padtype;
}
break; break;
} }

BIN
gx/images/Ctrl_ms4play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB