@@ -132,6 +132,8 @@ class specnext_state : public spectrum_128_state
132132 , m_io_video(*this , " VIDEO" )
133133 , m_io_layers(*this , " LYRS" )
134134 , m_io_mouse(*this , " mouse_input%u" , 1U )
135+ , m_io_joy_left(*this , " JOY_LEFT" )
136+ , m_io_joy_right(*this , " JOY_RIGHT" )
135137 {}
136138
137139 void tbblue (machine_config &config);
@@ -169,8 +171,9 @@ class specnext_state : public spectrum_128_state
169171 u8 port_ff_r ();
170172 void port_ff_w (u8 data);
171173 void turbosound_address_w (u8 data);
172- u8 mf_port_r (offs_t addr);
173- void mf_port_w (offs_t addr, u8 data);
174+ template <u8 Lsb> u8 mf_port_r (offs_t addr);
175+ template <u8 Lsb> void mf_port_w (offs_t addr, u8 data);
176+ template <u8 Joy> u8 kempston_md_r (offs_t addr);
174177 attotime copper_until_pos_r (u16 pos);
175178
176179 void bank_update (u8 bank, u8 count);
@@ -354,6 +357,8 @@ class specnext_state : public spectrum_128_state
354357 optional_ioport m_io_video;
355358 optional_ioport m_io_layers;
356359 required_ioport_array<3 > m_io_mouse;
360+ required_ioport m_io_joy_left;
361+ required_ioport m_io_joy_right;
357362
358363 video_timings_info m_video_timings;
359364 rectangle m_clip256x192;
@@ -386,8 +391,8 @@ class specnext_state : public spectrum_128_state
386391 u8 m_nr_03_machine_timing; // u3
387392 bool m_nr_03_config_mode;
388393 u8 m_nr_04_romram_bank; // u7
389- u8 m_nr_05_joy1 ; // u2
390- u8 m_nr_05_joy0 ; // u2
394+ u8 m_nr_05_joy0 ; // u3
395+ u8 m_nr_05_joy1 ; // u3
391396 bool m_nr_05_5060;
392397 u8 m_nr_06_psg_mode; // u2
393398 bool m_nr_06_ps2_mode;
@@ -1155,11 +1160,10 @@ void specnext_state::turbosound_address_w(u8 data)
11551160 m_ay[m_nr_08_psg_turbosound_en ? m_ay_select : 0 ]->address_w (data);
11561161}
11571162
1158- u8 specnext_state::mf_port_r (offs_t addr)
1163+ template < u8 Lsb> u8 specnext_state::mf_port_r (offs_t addr)
11591164{
11601165 if (!machine ().side_effects_disabled ())
11611166 {
1162- const u8 port = addr & 0xff ;
11631167 u8 port_mf_enable_io_a = 0x3f ;
11641168 u8 port_mf_disable_io_a = 0xbf ;
11651169 if (m_nr_0a_mf_type & 2 )
@@ -1173,8 +1177,8 @@ u8 specnext_state::mf_port_r(offs_t addr)
11731177 port_mf_disable_io_a = 0x3f ;
11741178 }
11751179
1176- m_mf->port_mf_enable_rd_w (port_multiface_io_en () && (port == port_mf_enable_io_a));
1177- m_mf->port_mf_disable_rd_w (port_multiface_io_en () && (port == port_mf_disable_io_a));
1180+ m_mf->port_mf_enable_rd_w (port_multiface_io_en () && (Lsb == port_mf_enable_io_a));
1181+ m_mf->port_mf_disable_rd_w (port_multiface_io_en () && (Lsb == port_mf_disable_io_a));
11781182 m_mf->port_mf_enable_wr_w (0 );
11791183 m_mf->port_mf_disable_wr_w (0 );
11801184 m_mf->clock_w ();
@@ -1184,7 +1188,7 @@ u8 specnext_state::mf_port_r(offs_t addr)
11841188
11851189 u8 data;
11861190 if (!m_mf->mf_port_en_r ())
1187- data = 0x00 ;
1191+ data = Lsb == 0x1f ? kempston_md_r< 0 >(addr) : 0x00 ;
11881192 else if (m_nr_0a_mf_type != 0b00 )
11891193 data = (BIT (m_port_7ffd_data, 3 ) << 7 ) | 0x7f ;
11901194 else
@@ -1207,9 +1211,48 @@ u8 specnext_state::mf_port_r(offs_t addr)
12071211 return data;
12081212}
12091213
1210- void specnext_state::mf_port_w (offs_t addr, u8 data)
1214+ template <u8 Joy> u8 specnext_state::kempston_md_r (offs_t addr)
1215+ {
1216+ u8 joyL_1f, joyL_37;
1217+ joyL_1f = joyL_37 = m_io_joy_left->read ();
1218+ const bool mdL_1f_en = m_nr_05_joy0 == 0b101 ;
1219+ const bool mdL_37_en = m_nr_05_joy0 == 0b110 ;
1220+ const bool joyL_1f_en = m_nr_05_joy0 == 0b001 || mdL_1f_en;
1221+ const bool joyL_37_en = m_nr_05_joy0 == 0b100 || mdL_37_en;
1222+
1223+ u8 joyR_1f, joyR_37;
1224+ joyR_1f = joyR_37 = m_io_joy_right->read ();;
1225+ const bool mdR_1f_en = m_nr_05_joy1 == 0b101 ;
1226+ const bool mdR_37_en = m_nr_05_joy1 == 0b110 ;
1227+ const bool joyR_1f_en = m_nr_05_joy1 == 0b001 || mdR_1f_en;
1228+ const bool joyR_37_en = m_nr_05_joy1 == 0b100 || mdR_37_en;
1229+
1230+ if (Joy == 0 && port_1f_io_en () && (joyL_1f_en || joyR_1f_en))
1231+ {
1232+ if (!mdL_1f_en) joyL_1f &= 0x3f ;
1233+ if (!joyL_1f_en) joyL_1f &= 0xc0 ;
1234+ if (!mdR_1f_en) joyR_1f &= 0x3f ;
1235+ if (!joyR_1f_en) joyR_1f &= 0xc0 ;
1236+
1237+ return joyL_1f | joyR_1f;
1238+ }
1239+ else if (Joy == 1 && port_37_io_en () && (joyL_37_en || joyR_37_en))
1240+ {
1241+ if (!mdL_37_en) joyL_37 &= 0x3f ;
1242+ if (!joyL_37_en) joyL_37 &= 0xc0 ;
1243+ if (!mdR_37_en) joyR_37 &= 0x3f ;
1244+ if (!joyR_37_en) joyR_37 &= 0xc0 ;
1245+
1246+ return joyL_37 | joyR_37;
1247+ }
1248+ else
1249+ {
1250+ return 0x00 ;
1251+ }
1252+ }
1253+
1254+ template <u8 Lsb> void specnext_state::mf_port_w (offs_t addr, u8 data)
12111255{
1212- const u8 port = addr & 0xff ;
12131256 u8 port_mf_enable_io_a = 0x3f ;
12141257 u8 port_mf_disable_io_a = 0xbf ;
12151258 if (m_nr_0a_mf_type & 2 )
@@ -1225,8 +1268,8 @@ void specnext_state::mf_port_w(offs_t addr, u8 data)
12251268
12261269 m_mf->port_mf_enable_rd_w (0 );
12271270 m_mf->port_mf_disable_rd_w (0 );
1228- m_mf->port_mf_enable_wr_w (port_multiface_io_en () && (port == port_mf_enable_io_a));
1229- m_mf->port_mf_disable_wr_w (port_multiface_io_en () && (port == port_mf_disable_io_a));
1271+ m_mf->port_mf_enable_wr_w (port_multiface_io_en () && (Lsb == port_mf_enable_io_a));
1272+ m_mf->port_mf_disable_wr_w (port_multiface_io_en () && (Lsb == port_mf_disable_io_a));
12301273 m_mf->clock_w ();
12311274 bank_update (0 , 2 );
12321275 m_mf->port_mf_enable_rd_w (0 );
@@ -1675,7 +1718,11 @@ u8 specnext_state::reg_r(offs_t nr_register)
16751718 port_253b_dat = 0 ;// (i_KBD_EXTENDED_KEYS(12) <<) | (i_KBD_EXTENDED_KEYS(7 downto 2) <<) | i_KBD_EXTENDED_KEYS(0);
16761719 break ;
16771720 case 0xb2 :
1678- port_253b_dat = 0 ;// (i_JOY_RIGHT(10 downto 8) <<) | (i_JOY_RIGHT(11) <<) | (i_JOY_LEFT(10 downto 8) <<) | i_JOY_LEFT(11);
1721+ {
1722+ u16 i_joy_left = m_io_joy_left->read ();
1723+ u16 i_joy_right = m_io_joy_right->read ();
1724+ port_253b_dat = (BIT (i_joy_right, 8 , 3 ) << 5 ) | (BIT (i_joy_right, 11 ) << 4 ) | (BIT (i_joy_left, 8 , 3 ) << 1 ) | BIT (i_joy_right, 11 );
1725+ }
16791726 break ;
16801727 case 0xb8 :
16811728 port_253b_dat = m_nr_b8_divmmc_ep_0;
@@ -2733,30 +2780,10 @@ void specnext_state::map_io(address_map &map)
27332780 map (0x0000 , 0x0000 ).select (0xfffe ).rw (FUNC (specnext_state::spectrum_ula_r), FUNC (specnext_state::spectrum_ula_w));
27342781 map (0x00ff , 0x00ff ).mirror (0xff00 ).rw (FUNC (specnext_state::port_ff_r), FUNC (specnext_state::port_ff_w));
27352782
2736- map (0x001f , 0x001f ).select (0xff00 ).lrw8 (NAME ([this ](offs_t offset)
2737- {
2738- return mf_port_r (offset | 0x1f );
2739- }), NAME ([this ](offs_t offset, u8 data) {
2740- mf_port_w (offset | 0x1f , data);
2741- }));
2742- map (0x003f , 0x003f ).select (0xff00 ).lrw8 (NAME ([this ](offs_t offset)
2743- {
2744- return mf_port_r (offset | 0x3f );
2745- }), NAME ([this ](offs_t offset, u8 data) {
2746- mf_port_w (offset | 0x3f , data);
2747- }));
2748- map (0x009f , 0x009f ).select (0xff00 ).lrw8 (NAME ([this ](offs_t offset)
2749- {
2750- return mf_port_r (offset | 0x8f );
2751- }), NAME ([this ](offs_t offset, u8 data) {
2752- mf_port_w (offset | 0x8f , data);
2753- }));
2754- map (0x00bf , 0x00bf ).select (0xff00 ).lrw8 (NAME ([this ](offs_t offset)
2755- {
2756- return mf_port_r (offset | 0xbf );
2757- }), NAME ([this ](offs_t offset, u8 data) {
2758- mf_port_w (offset | 0xbf , data);
2759- }));
2783+ map (0x001f , 0x001f ).select (0xff00 ).rw (FUNC (specnext_state::mf_port_r<0x1f >), FUNC (specnext_state::mf_port_w<0x1f >));
2784+ map (0x003f , 0x003f ).select (0xff00 ).rw (FUNC (specnext_state::mf_port_r<0x3f >), FUNC (specnext_state::mf_port_w<0x3f >));
2785+ map (0x009f , 0x009f ).select (0xff00 ).rw (FUNC (specnext_state::mf_port_r<0x9f >), FUNC (specnext_state::mf_port_w<0x9f >));
2786+ map (0x00bf , 0x00bf ).select (0xff00 ).rw (FUNC (specnext_state::mf_port_r<0xbf >), FUNC (specnext_state::mf_port_w<0xbf >));
27602787
27612788 map (0x0001 , 0x0001 ).mirror (0xfff4 ).lr8 (NAME ([this ]() { // #bff5
27622789 return m_nr_08_psg_turbosound_en ? m_ay_select : 0 ;
@@ -2897,6 +2924,8 @@ void specnext_state::map_io(address_map &map)
28972924 map (0x0fdf , 0x0fdf ).mirror (0xf000 ).lr8 (NAME ([this ]() -> u8 { return ~m_io_mouse[1 ]->read (); })); // #ffdf
28982925 map (0x0adf , 0x0adf ).mirror (0xf000 ).lr8 (NAME ([this ]() -> u8 { return 0x80 | (m_io_mouse[2 ]->read () & 0x07 ); })); // #fadf
28992926
2927+ map (0x0037 , 0x0037 ).mirror (0xff00 ).r (FUNC (specnext_state::kempston_md_r<1 >));
2928+
29002929 // TODO resolve conflicts mf+joy+DAC: 1f, 3f
29012930 // map(0x001f, 0x001f).mirror(0xff00).lr8(NAME([]() -> u8 { return 0x00; /* Joy1,2*/ })).lw8(NAME([this](u8 data) {
29022931 // if (m_nr_08_dac_en)
@@ -2989,6 +3018,34 @@ INPUT_PORTS_START(specnext)
29893018 PORT_BIT (0x02 , IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME(" Right mouse button" ) PORT_CODE(MOUSECODE_BUTTON1)
29903019 PORT_BIT (0x04 , IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME(" Middle mouse button" ) PORT_CODE(MOUSECODE_BUTTON3)
29913020
3021+ PORT_START (" JOY_LEFT" )
3022+ PORT_BIT (0x001 , IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_HAT1RIGHT) PORT_NAME(" Joystick (L) Right" ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_8WAY
3023+ PORT_BIT (0x002 , IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_HAT1LEFT) PORT_NAME(" Joystick (L) Left" ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_8WAY
3024+ PORT_BIT (0x004 , IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_HAT1DOWN) PORT_NAME(" Joystick (L) Down" ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_8WAY
3025+ PORT_BIT (0x008 , IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_HAT1UP) PORT_NAME(" Joystick (L) Up" ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_8WAY
3026+ PORT_BIT (0x010 , IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON2) PORT_NAME(" Joystick (L) B" )
3027+ PORT_BIT (0x020 , IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON5) PORT_NAME(" Joystick (L) C" )
3028+ PORT_BIT (0x040 , IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON1) PORT_NAME(" Joystick (L) A" )
3029+ PORT_BIT (0x080 , IP_ACTIVE_HIGH, IPT_BUTTON8) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON8) PORT_NAME(" Joystick (L) Start" )
3030+ PORT_BIT (0x100 , IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON4) PORT_NAME(" Joystick (L) Y" )
3031+ PORT_BIT (0x200 , IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON6) PORT_NAME(" Joystick (L) Z" )
3032+ PORT_BIT (0x400 , IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON3) PORT_NAME(" Joystick (L) X" )
3033+ PORT_BIT (0x800 , IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON7) PORT_NAME(" Joystick (L) Mode" )
3034+
3035+ PORT_START (" JOY_RIGHT" )
3036+ PORT_BIT (0x001 , IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_HAT1RIGHT) PORT_NAME(" Joystick (R) Right" ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_8WAY
3037+ PORT_BIT (0x002 , IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_HAT1LEFT) PORT_NAME(" Joystick (R) Left" ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_8WAY
3038+ PORT_BIT (0x004 , IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_HAT1DOWN) PORT_NAME(" Joystick (R) Down" ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_8WAY
3039+ PORT_BIT (0x008 , IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_HAT1UP) PORT_NAME(" Joystick (R) Up" ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_8WAY
3040+ PORT_BIT (0x010 , IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_BUTTON2) PORT_NAME(" Joystick (R) B" )
3041+ PORT_BIT (0x020 , IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_BUTTON5) PORT_NAME(" Joystick (R) C" )
3042+ PORT_BIT (0x040 , IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_BUTTON1) PORT_NAME(" Joystick (R) A" )
3043+ PORT_BIT (0x080 , IP_ACTIVE_HIGH, IPT_BUTTON8) PORT_PLAYER(2 ) PORT_CODE(JOYCODE_BUTTON8) PORT_NAME(" Joystick (R) Start" )
3044+ PORT_BIT (0x100 , IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON4) PORT_NAME(" Joystick (R) Y" )
3045+ PORT_BIT (0x200 , IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON6) PORT_NAME(" Joystick (R) Z" )
3046+ PORT_BIT (0x400 , IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON3) PORT_NAME(" Joystick (R) X" )
3047+ PORT_BIT (0x800 , IP_ACTIVE_HIGH, IPT_BUTTON7) PORT_PLAYER(1 ) PORT_CODE(JOYCODE_BUTTON7) PORT_NAME(" Joystick (R) Mode" )
3048+
29923049 PORT_MODIFY (" NMI" )
29933050 PORT_BIT (0x01 , IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME(" NMI MF" ) PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_mf_nmi), 0 )
29943051 PORT_BIT (0x02 , IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME(" NMI DivMMC" ) PORT_CODE(KEYCODE_F11) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(specnext_state::on_divmmc_nmi), 0 )
0 commit comments