From 1ebbe17e7f1cb3f63ff8d99e147b6f28cad5da57 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Sat, 15 Jun 2013 16:30:05 +0000 Subject: [PATCH] (MESS) NES input cleanup, part 5 and last (Simplified FC input too, added Arkanoid FC paddle emulation, fixed P3 & P4 inputs in Jpn games using them). nw. paddle now works in Chase HQ too (the NES one don't because of the different protocol), 3rd & 4th players can enter inputs in Technos games, and it turned out that Lightgun was actually working (I had probably tested with a non-clean compile), so that at last all selectable input devices are finally working :-) --- src/mess/drivers/nes.c | 57 +++---- src/mess/includes/nes.h | 3 +- src/mess/machine/nes.c | 325 ++++++++++++++++++++-------------------- 3 files changed, 197 insertions(+), 188 deletions(-) diff --git a/src/mess/drivers/nes.c b/src/mess/drivers/nes.c index 8c77d904f07..71d8441aa14 100644 --- a/src/mess/drivers/nes.c +++ b/src/mess/drivers/nes.c @@ -59,7 +59,7 @@ ADDRESS_MAP_END static INPUT_PORTS_START( nes_pads12 ) - PORT_START("PAD1") /* Joypad 1 */ + PORT_START("PAD1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) @@ -69,7 +69,7 @@ static INPUT_PORTS_START( nes_pads12 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) - PORT_START("PAD2") /* Joypad 2 */ + PORT_START("PAD2") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) @@ -82,7 +82,7 @@ static INPUT_PORTS_START( nes_pads12 ) INPUT_PORTS_END static INPUT_PORTS_START( nes_pads34 ) - PORT_START("PAD3") /* Joypad 3 */ + PORT_START("PAD3") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 A") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 B") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) @@ -92,7 +92,7 @@ static INPUT_PORTS_START( nes_pads34 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) - PORT_START("PAD4") /* Joypad 4 */ + PORT_START("PAD4") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 A") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 B") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) @@ -105,27 +105,27 @@ static INPUT_PORTS_START( nes_pads34 ) INPUT_PORTS_END static INPUT_PORTS_START( nes_zapper1 ) - PORT_START("ZAPPER1_X") /* P1 zapper */ + PORT_START("ZAPPER1_X") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) - PORT_START("ZAPPER1_Y") /* P1 zapper */ + PORT_START("ZAPPER1_Y") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) - PORT_START("ZAPPER1_T") /* P1 zapper trigger */ + PORT_START("ZAPPER1_T") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002) INPUT_PORTS_END static INPUT_PORTS_START( nes_zapper2 ) - PORT_START("ZAPPER2_X") /* P2 zapper */ + PORT_START("ZAPPER2_X") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) - PORT_START("ZAPPER2_Y") /* P2 zapper */ + PORT_START("ZAPPER2_Y") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) - PORT_START("ZAPPER2_T") /* P2 zapper trigger */ + PORT_START("ZAPPER2_T") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020) INPUT_PORTS_END static INPUT_PORTS_START( nes_paddle ) - PORT_START("PADDLE") /* Arkanoid paddle */ + PORT_START("PADDLE") PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040) - PORT_START("PADDLE_BUTTON") /* Arkanoid paddle button */ + PORT_START("PADDLE_BUTTON") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040) INPUT_PORTS_END @@ -136,7 +136,7 @@ static INPUT_PORTS_START( nes ) PORT_INCLUDE( nes_zapper2 ) PORT_INCLUDE( nes_paddle ) - PORT_START("CTRLSEL") /* Select Controller Type */ + PORT_START("CTRLSEL") PORT_CONFNAME( 0x000f, 0x0001, "P1 Controller") PORT_CONFSETTING( 0x0000, "Unconnected" ) PORT_CONFSETTING( 0x0001, "Gamepad" ) @@ -154,7 +154,7 @@ static INPUT_PORTS_START( nes ) PORT_CONFSETTING( 0x0000, "Unconnected" ) PORT_CONFSETTING( 0x1000, "Gamepad" ) - PORT_START("CONFIG") /* configuration */ + PORT_START("CONFIG") PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines") PORT_CONFSETTING( 0x01, DEF_STR(No) ) PORT_CONFSETTING( 0x00, DEF_STR(Yes) ) @@ -165,7 +165,7 @@ INPUT_PORTS_END static INPUT_PORTS_START( fc_pads12 ) - PORT_START("PAD1") /* Joypad 1 */ + PORT_START("PAD1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) @@ -175,7 +175,7 @@ static INPUT_PORTS_START( fc_pads12 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001) - PORT_START("PAD2") /* Joypad 2 */ + PORT_START("PAD2") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010) @@ -188,7 +188,7 @@ static INPUT_PORTS_START( fc_pads12 ) INPUT_PORTS_END static INPUT_PORTS_START( fc_pads34 ) - PORT_START("PAD3") /* Joypad 3 */ + PORT_START("PAD3") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 A") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 B") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) @@ -198,7 +198,7 @@ static INPUT_PORTS_START( fc_pads34 ) PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100) - PORT_START("PAD4") /* Joypad 4 */ + PORT_START("PAD4") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 A") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 B") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000) @@ -210,17 +210,19 @@ static INPUT_PORTS_START( fc_pads34 ) INPUT_PORTS_END static INPUT_PORTS_START( fc_lightgun ) - PORT_START("ZAPPER2_X") /* P2 zapper */ + PORT_START("ZAPPER2_X") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01) - PORT_START("ZAPPER2_Y") /* P2 zapper */ + PORT_START("ZAPPER2_Y") PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01) - PORT_START("ZAPPER2_T") /* P2 zapper trigger */ + PORT_START("ZAPPER2_T") PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01) INPUT_PORTS_END static INPUT_PORTS_START( fc_paddle ) - PORT_START("PADDLE") /* Arkanoid paddle */ - PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(3) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x04) + PORT_START("PADDLE") + PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x04) + PORT_START("PADDLE_BUTTON") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button") PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x04) INPUT_PORTS_END static INPUT_PORTS_START( fc_cclimb ) @@ -502,6 +504,7 @@ static INPUT_PORTS_START( famicom ) PORT_INCLUDE( fc_pads12 ) PORT_INCLUDE( fc_pads34 ) PORT_INCLUDE( fc_lightgun ) + // FIXME: was it possible to attache two paddles in a Famicom (as the Arkanoid 2 box suggests)?!? investigate... PORT_INCLUDE( fc_paddle ) // Crazy Climber is not really a separate controller, but a couple of small sticks to be // put on top of d-pads of the regular controllers. Users should then control the game @@ -511,7 +514,7 @@ static INPUT_PORTS_START( famicom ) PORT_INCLUDE( subor_keyboard ) PORT_INCLUDE( mahjong_panel ) - PORT_START("CTRLSEL") /* Select Controller Type */ + PORT_START("CTRLSEL") PORT_CONFNAME( 0x000f, 0x0001, "P1 Controller") PORT_CONFSETTING( 0x0000, "Unconnected" ) PORT_CONFSETTING( 0x0001, "Gamepad" ) @@ -527,7 +530,7 @@ static INPUT_PORTS_START( famicom ) PORT_CONFSETTING( 0x0000, "Unconnected" ) PORT_CONFSETTING( 0x1000, "Gamepad" ) - PORT_START("EXP") /* expansion port */ + PORT_START("EXP") PORT_CONFNAME( 0x0f, 0x00, "Expansion Port") PORT_CONFSETTING( 0x00, "(Empty)" ) PORT_CONFSETTING( 0x01, "Light Gun" ) @@ -538,7 +541,7 @@ static INPUT_PORTS_START( famicom ) PORT_CONFSETTING( 0x06, "Mahjong Panel" ) PORT_CONFSETTING( 0x07, "Hori Twin Adapter" ) - PORT_START("CONFIG") /* configuration */ + PORT_START("CONFIG") PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines") PORT_CONFSETTING( 0x01, DEF_STR(No) ) PORT_CONFSETTING( 0x00, DEF_STR(Yes) ) @@ -546,7 +549,7 @@ static INPUT_PORTS_START( famicom ) PORT_CONFSETTING( 0x02, DEF_STR(No) ) PORT_CONFSETTING( 0x00, DEF_STR(Yes) ) - PORT_START("FLIPDISK") /* fake keys */ + PORT_START("FLIPDISK") /* fake key */ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Change Disk Side") INPUT_PORTS_END diff --git a/src/mess/includes/nes.h b/src/mess/includes/nes.h index c22527589c4..e975278ac82 100644 --- a/src/mess/includes/nes.h +++ b/src/mess/includes/nes.h @@ -555,9 +555,10 @@ public: void fds_irq(int scanline, int vblank, int blanked); - UINT32 m_pad_latch[2]; + UINT32 m_pad_latch[4]; UINT8 m_zapper_latch[2][3]; UINT8 m_paddle_latch, m_paddle_btn_latch; + UINT8 m_mjpanel_latch; protected: virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); diff --git a/src/mess/machine/nes.c b/src/mess/machine/nes.c index b235d16bb5d..458721a00b0 100644 --- a/src/mess/machine/nes.c +++ b/src/mess/machine/nes.c @@ -81,6 +81,7 @@ static void nes_state_register( running_machine &machine ) state->save_item(NAME(state->m_zapper_latch)); state->save_item(NAME(state->m_paddle_latch)); state->save_item(NAME(state->m_paddle_btn_latch)); + state->save_item(NAME(state->m_mjpanel_latch)); } @@ -245,7 +246,7 @@ READ8_MEMBER(nes_state::nes_in0_r) } if (LOG_JOY) - logerror("joy 0 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_0.shift, m_in_0.i0); + logerror("joy 0 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc()); return ret; } @@ -296,7 +297,7 @@ READ8_MEMBER(nes_state::nes_in1_r) } if (LOG_JOY) - logerror("joy 1 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_1.shift, m_in_1.i0); + logerror("joy 1 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc()); return ret; } @@ -304,7 +305,10 @@ READ8_MEMBER(nes_state::nes_in1_r) WRITE8_MEMBER(nes_state::nes_in0_w) { int cfg = m_io_ctrlsel->read(); - + + if (LOG_JOY) + logerror("joy write, val: %02x, pc: %04x\n", data, space.device().safe_pc()); + // Check if lightgun has been chosen as input: if so, enable crosshair timer_set(attotime::zero, TIMER_ZAPPER_TICK); @@ -319,7 +323,8 @@ WRITE8_MEMBER(nes_state::nes_in0_w) m_zapper_latch[0][2] = 0; m_zapper_latch[1][0] = 0; m_zapper_latch[1][1] = 0; - m_zapper_latch[1][2] = 0; + m_zapper_latch[1][2] = 0; + m_paddle_btn_latch = 0; m_paddle_latch = 0; // P1 inputs @@ -354,7 +359,8 @@ WRITE8_MEMBER(nes_state::nes_in0_w) m_paddle_latch = (UINT8) (m_io_paddle->read() ^ 0xff); break; } - + + // P3 & P4 inputs in NES Four Score are read serially with P1 & P2 // P3 inputs if ((cfg & 0x0f00)) m_pad_latch[0] |= ((m_io_pad[2]->read() << 8) | (0x08 << 16)); // pad 3 + signature @@ -373,29 +379,46 @@ WRITE8_MEMBER(nes_state::nes_in1_w) READ8_MEMBER(nes_state::fc_in0_r) { int exp = m_io_exp->read(); - /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ - /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */ - UINT8 ret = 0x40; - if ((exp & 0x0f) == 0x02) - { - // tape input - if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) - { - double level = m_cassette->input(); - if (level < 0) - ret |= 0x00; - else - ret |= 0x02; - } + // Some games expect bit 6 to be set because the last entry on the data bus shows up + // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. + UINT8 ret = 0x40; + ret |= (m_pad_latch[0] & 0x01); + + // shift + m_pad_latch[0] >>= 1; + + // EXP input + switch (exp & 0x0f) + { + case 0x02: // FC Keyboard: tape input + if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) + { + double level = m_cassette->input(); + if (level < 0) + ret |= 0x00; + else + ret |= 0x02; + } + break; + + case 0x04: // Arkanoid paddle + ret |= (m_paddle_btn_latch << 1); // button + break; + + case 0x06: // Mahjong Panel + ret |= ((m_mjpanel_latch & 0x01) << 1); + m_mjpanel_latch >>= 1; + break; + + case 0x07: // 'multitap' p3 + ret |= ((m_pad_latch[2] & 0x01) << 1); + m_pad_latch[2] >>= 1; + break; } - ret |= ((m_in_0.i0 >> m_in_0.shift) & 0x01); - if (LOG_JOY) - logerror("joy 0 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_0.shift, m_in_0.i0); - - m_in_0.shift++; + logerror("joy 0 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc()); return ret; } @@ -403,75 +426,76 @@ READ8_MEMBER(nes_state::fc_in0_r) READ8_MEMBER(nes_state::fc_in1_r) { int exp = m_io_exp->read(); - /* Some games expect bit 6 to be set because the last entry on the data bus shows up */ - /* in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. */ + + // Some games expect bit 6 to be set because the last entry on the data bus shows up + // in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there. UINT8 ret = 0x40; + ret |= (m_pad_latch[1] & 0x01); - // row of the keyboard matrix are read 4-bits at time, and gets returned as bit1->bit4 - if ((exp & 0x0f) == 0x02) + // shift + m_pad_latch[1] >>= 1; + + + // EXP input + switch (exp & 0x0f) { - if (m_fck_scan < 9) - ret |= ~(((m_io_fckey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; - else - ret |= 0x1e; - } - - if ((exp & 0x0f) == 0x03) - { - if (m_fck_scan < 12) - ret |= ~(((m_io_subkey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; - else - ret |= 0x1e; - } - - /* Handle data line 0's serial output */ - if ((exp & 0x0f) == 0x06) - ret |= (((m_in_1.i0 >> m_in_1.shift) & 0x01) << 1); - else - ret |= ((m_in_1.i0 >> m_in_1.shift) & 0x01); - - /* zapper */ - if ((exp & 0x0f) == 0x01) - { - int x = m_in_1.i1; /* read Zapper x-position */ - int y = m_in_1.i2; /* read Zapper y-position */ - UINT32 pix, color_base; - - /* get the pixel at the gun position */ - pix = m_ppu->get_pixel(x, y); - - /* get the color base from the ppu */ - color_base = m_ppu->get_colorbase(); - - /* look at the screen and see if the cursor is over a bright pixel */ - if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || - (pix == color_base + 0x33) || (pix == color_base + 0x34)) - { - ret &= ~0x08; /* sprite hit */ - } - else - ret |= 0x08; /* no sprite hit */ - - /* If button 1 is pressed, indicate the light gun trigger is pressed */ - ret |= ((m_in_1.i0 & 0x01) << 4); - } - - /* arkanoid dial */ - if ((exp & 0x0f) == 0x04) - { - /* Handle data line 2's serial output */ - ret |= ((m_in_1.i2 >> m_in_1.shift) & 0x01) << 3; - - /* Handle data line 3's serial output - bits are reversed */ - /* NPW 27-Nov-2007 - there is no third subscript! commenting out */ - /* ret |= ((m_in_1[3] >> m_in_1.shift) & 0x01) << 4; */ - /* ret |= ((m_in_1[3] << m_in_1.shift) & 0x80) >> 3; */ + case 0x01: // Lightgun + { + int x = m_zapper_latch[0][1]; // x-position + int y = m_zapper_latch[0][2]; // y-position + UINT32 pix, color_base; + + // get the pixel at the gun position + pix = m_ppu->get_pixel(x, y); + + // get the color base from the ppu + color_base = m_ppu->get_colorbase(); + + // check if the cursor is over a bright pixel + if ((pix == color_base + 0x20) || (pix == color_base + 0x30) || + (pix == color_base + 0x33) || (pix == color_base + 0x34)) + ret &= ~0x08; // sprite hit + else + ret |= 0x08; // no sprite hit + + // light gun trigger + ret |= (m_zapper_latch[0][0] << 4); + } + break; + + case 0x02: // FC Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4 + if (m_fck_scan < 9) + ret |= ~(((m_io_fckey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; + else + ret |= 0x1e; + break; + + case 0x03: // Subor Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4 + if (m_fck_scan < 12) + ret |= ~(((m_io_subkey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e; + else + ret |= 0x1e; + break; + + case 0x04: // Arkanoid paddle + ret |= ((m_paddle_latch & 0x80) >> 6); // paddle data + m_paddle_latch <<= 1; + m_paddle_latch &= 0xff; + break; + + case 0x06: // Mahjong Panel + ret |= ((m_mjpanel_latch & 0x01) << 1); + m_mjpanel_latch >>= 1; + break; + + case 0x07: // 'multitap' p4 + ret |= ((m_pad_latch[3] & 0x01) << 1); + m_pad_latch[3] >>= 1; + break; } if (LOG_JOY) - logerror("joy 1 read, val: %02x, pc: %04x, bits read: %d, chan0: %08x\n", ret, space.device().safe_pc(), m_in_1.shift, m_in_1.i0); - - m_in_1.shift++; + logerror("joy 1 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc()); return ret; } @@ -480,8 +504,11 @@ WRITE8_MEMBER(nes_state::fc_in0_w) { int cfg = m_io_ctrlsel->read(); int exp = m_io_exp->read(); - - /* Check if lightgun has been chosen as input: if so, enable crosshair */ + + if (LOG_JOY) + logerror("joy write, val: %02x, pc: %04x\n", data, space.device().safe_pc()); + + // Check if lightgun has been chosen as input: if so, enable crosshair timer_set(attotime::zero, TIMER_LIGHTGUN_TICK); if ((exp & 0x0f) == 0x02 || (exp & 0x0f) == 0x03) @@ -504,106 +531,84 @@ WRITE8_MEMBER(nes_state::fc_in0_w) m_fck_scan = 0; } } - - // check 'standard' inputs + if (data & 0x01) return; - if (LOG_JOY) - logerror("joy 0 bits read: %d\n", m_in_0.shift); - - /* Toggling bit 0 high then low resets both controllers */ - m_in_0.shift = 0; - m_in_1.shift = 0; - m_in_0.i0 = 0; - m_in_0.i1 = 0; - m_in_0.i2 = 0; - m_in_1.i0 = 0; - m_in_1.i1 = 0; - m_in_1.i2 = 0; - m_in_2.i0 = 0; - m_in_2.i1 = 0; - m_in_2.i2 = 0; - m_in_3.i0 = 0; - m_in_3.i1 = 0; - m_in_3.i2 = 0; + // Toggling bit 0 high then low resets controllers + m_pad_latch[0] = 0; + m_pad_latch[1] = 0; + m_pad_latch[2] = 0; + m_pad_latch[3] = 0; + m_zapper_latch[0][0] = 0; + m_zapper_latch[0][1] = 0; + m_zapper_latch[0][2] = 0; + m_paddle_btn_latch = 0; + m_paddle_latch = 0; + m_mjpanel_latch = 0; // P1 inputs - if ((cfg & 0x000f) == 0x0001) /* gamepad 1 */ - m_in_0.i0 = m_io_pad[0]->read(); - else if ((cfg & 0x000f) == 0x0002) /* crazy climber controller (left stick) */ - m_in_0.i0 = m_io_cc_left->read(); + switch (cfg & 0x000f) + { + case 0x01: // pad 1 + m_pad_latch[0] = m_io_pad[0]->read(); + break; + + case 0x02: // crazy climber (left stick) + m_pad_latch[0] = m_io_cc_left->read(); + break; + } // P2 inputs - if ((cfg & 0x00f0) == 0x0010) /* gamepad 2 */ - m_in_1.i0 = m_io_pad[1]->read(); - else if ((cfg & 0x00f0) == 0x0020) /* crazy climber controller (right stick) */ - m_in_1.i0 = m_io_cc_right->read(); + switch ((cfg & 0x00f0) >> 4) + { + case 0x01: // pad 2 + m_pad_latch[1] = m_io_pad[1]->read(); + break; + + case 0x02: // crazy climber (right stick) + m_pad_latch[1] = m_io_cc_right->read(); + break; + + } + // P3 & P4 inputs in Famicom (e.g. through Hori Twin Adapter or Hori 4 Players Adapter) + // are read in parallel with P1 & P2 (just using diff bits) // P3 inputs if ((exp & 0x0f) == 7 && (cfg & 0x0f00) == 0x0100) - { - m_in_2.i0 = m_io_pad[2]->read(); - m_in_0.i0 |= (m_in_2.i0 << 8) | (0x08 << 16); - } + m_pad_latch[2] = m_io_pad[2]->read(); // pad 3 // P4 inputs if ((exp & 0x0f) == 7 && (cfg & 0xf000) == 0x1000) - { - m_in_3.i0 = m_io_pad[3]->read(); - m_in_1.i0 |= (m_in_3.i0 << 8) | (0x04 << 16); - } + m_pad_latch[3] = m_io_pad[3]->read(); // pad 4 + - // EXP input switch (exp & 0x0f) { case 0x01: // Lightgun - m_in_0.i0 = m_io_zapper2_t->read(); - m_in_0.i1 = m_io_zapper2_x->read(); - m_in_0.i2 = m_io_zapper2_y->read(); + m_zapper_latch[0][0] = m_io_zapper2_t->read(); + m_zapper_latch[0][1] = m_io_zapper2_x->read(); + m_zapper_latch[0][2] = m_io_zapper2_y->read(); break; -#if 0 + case 0x02: // FC Keyboard - // here we should also have the tape output - if (BIT(data, 2)) // keyboard active - { - UINT8 out = BIT(data, 1); // scan - - if (m_fck_mode && !out && ++m_fck_scan > 9) - m_fck_scan = 0; - - m_fck_mode = out; // access lower or upper 4 bits - - if (BIT(data, 0)) // reset - m_fck_scan = 0; - } - break; - case 0x03: // Subor Keyboard - if (BIT(data, 2)) // keyboard active - { - UINT8 out = BIT(data, 1); // scan - - if (m_fck_mode && !out && ++m_fck_scan > 12) - m_fck_scan = 0; - - m_fck_mode = out; // access lower or upper 4 bits - - if (BIT(data, 0)) // reset - m_fck_scan = 0; - } + // these are scanned differently than other devices: + // writes to $4016 with bit2 set always update the + // line counter and writing bit0 set resets the counter break; -#endif + case 0x04: // Arkanoid paddle - m_in_1.i0 |= (UINT8) ((UINT8) m_io_paddle->read() + (UINT8)0x52) ^ 0xff; + m_paddle_btn_latch = m_io_paddle_btn->read(); + m_paddle_latch = (UINT8) (m_io_paddle->read() ^ 0xff); break; case 0x06: // Mahjong Panel if (data & 0xf8) logerror("Error: Mahjong panel read with mux data %02x\n", (data & 0xfe)); else - m_in_1.i0 = m_io_mahjong[(data & 0xfe) >> 1]->read(); + m_mjpanel_latch = m_io_mahjong[(data & 0xfe) >> 1]->read(); break; }