Previous 199869 Revisions Next

r22681 Monday 6th May, 2013 at 00:09:10 UTC by Carl
(mess) psxmultitap: add multitap support [Carl]
[src/mess]mess.mak
[src/mess/machine]psxcard.c psxcard.h psxcport.c psxcport.h psxmultitap.c* psxmultitap.h*

trunk/src/mess/machine/psxcard.c
r22680r22681
5151   m_ack_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(psxcard_device::ack_timer), this));
5252
5353   m_ack = true;
54   m_disabled = false;
5455
5556   // save state registrations
5657/*  save_item(NAME(pkt));
r22680r22681
9596   switch (state)
9697   {
9798      case state_illegal:
98         if ((to == 0x81) && is_loaded())
99         if (is_loaded())
99100         {
100101//              printf("CARD: begin\n");
101102            state = state_command;
r22680r22681
277278
278279bool psxcard_device::call_load()
279280{
281   if(m_disabled)
282   {
283      logerror("psxcard: port disabled\n");
284      return IMAGE_INIT_FAIL;
285   }
286
280287   if(length() != card_size)
281288      return IMAGE_INIT_FAIL;
282289   return IMAGE_INIT_PASS;
r22680r22681
287294   UINT8 block[block_size];
288295   int i, ret;
289296
297   if(m_disabled)
298   {
299      logerror("psxcard: port disabled\n");
300      return IMAGE_INIT_FAIL;
301   }
302
290303   memset(block, '\0', block_size);
291304   for(i = 0; i < (card_size/block_size); i++)
292305   {
trunk/src/mess/machine/psxcard.h
r22680r22681
2929   virtual bool call_load();
3030   virtual bool call_create(int format_type, option_resolution *format_options);
3131
32   void disable(bool state) { m_disabled = state; if(state) unload(); }
33
3234private:
3335   unsigned char pkt[0x8b], pkt_ptr, pkt_sz, cmd;
3436   unsigned short addr;
3537   int state;
38   bool m_disabled;
3639
3740   UINT8 m_odata;
3841   UINT8 m_idata;
trunk/src/mess/machine/psxcport.c
r22680r22681
22
33#include "machine/psxcport.h"
44#include "machine/psxanalog.h"
5#include "machine/psxmultitap.h"
56
67const device_type PSX_CONTROLLER_PORT = &device_creator<psx_controller_port_device>;
78
r22680r22681
2627   return MACHINE_CONFIG_NAME( psx_memory_card );
2728}
2829
30void psx_controller_port_device::disable_card(bool state)
31{
32   if(state)
33      popmessage("Memory card port %s is disabled\n", m_card->brief_instance_name());
34
35   m_card->disable(state);
36}
37
2938const device_type PSXCONTROLLERPORTS = &device_creator<psxcontrollerports_device>;
3039
3140psxcontrollerports_device::psxcontrollerports_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
r22680r22681
4251   psxsiodev_device::device_start();
4352}
4453
54// add controllers to define so they can be connected to the multitap
55#define PSX_CONTROLLERS \
56      SLOT_INTERFACE("digital_pad", PSX_STANDARD_CONTROLLER) \
57      SLOT_INTERFACE("dualshock_pad", PSX_DUALSHOCK) \
58      SLOT_INTERFACE("analog_joystick", PSX_ANALOG_JOYSTICK)
59
4560SLOT_INTERFACE_START(psx_controllers)
46   SLOT_INTERFACE("digital_pad", PSX_STANDARD_CONTROLLER)
47   SLOT_INTERFACE("dualshock_pad", PSX_DUALSHOCK)
48   SLOT_INTERFACE("analog_joystick", PSX_ANALOG_JOYSTICK)
61   PSX_CONTROLLERS
62   SLOT_INTERFACE("multitap", PSX_MULTITAP)
4963SLOT_INTERFACE_END
5064
65SLOT_INTERFACE_START(psx_controllers_nomulti)
66   PSX_CONTROLLERS
67SLOT_INTERFACE_END
68
5169void psxcontrollerports_device::data_in( int data, int mask )
5270{
5371   m_port0->sel_w((data & PSX_SIO_OUT_DTR)?1:0);
trunk/src/mess/machine/psxcport.h
r22680r22681
2020
2121class device_psx_controller_interface : public device_slot_card_interface
2222{
23   friend class psx_multitap_device;
2324public:
2425   device_psx_controller_interface(const machine_config &mconfig, device_t &device);
2526   virtual ~device_psx_controller_interface();
r22680r22681
112113   DECLARE_READ_LINE_MEMBER(ack_r) { return (m_dev?m_dev->ack_r():true) && m_card->ack_r(); }
113114   DECLARE_READ_LINE_MEMBER(tx_r) { return m_tx; }
114115
116   void disable_card(bool status);
117
115118protected:
116119   virtual void device_start() {}
117120   virtual void device_reset() { m_tx = true; }
trunk/src/mess/machine/psxmultitap.c
r0r22681
1// psx multitap emulation
2
3#include "machine/psxmultitap.h"
4
5const device_type PSX_MULTITAP = &device_creator<psx_multitap_device>;
6
7psx_multitap_device::psx_multitap_device(const machine_config& mconfig, const char* tag, device_t* owner, UINT32 clock) :
8   device_t(mconfig, PSX_MULTITAP, "Playstation Multitap", tag, owner, clock),
9   device_psx_controller_interface(mconfig, *this),
10   m_porta(*this, "a"),
11   m_portb(*this, "b"),
12   m_portc(*this, "c"),
13   m_portd(*this, "d")
14{
15}
16
17static MACHINE_CONFIG_FRAGMENT( psx_multitap )
18   MCFG_PSX_CTRL_PORT_ADD("a", psx_controllers_nomulti, "digital_pad", NULL)
19   MCFG_PSX_CTRL_PORT_ADD("b", psx_controllers_nomulti, NULL, NULL)
20   MCFG_PSX_CTRL_PORT_ADD("c", psx_controllers_nomulti, NULL, NULL)
21   MCFG_PSX_CTRL_PORT_ADD("d", psx_controllers_nomulti, NULL, NULL)
22MACHINE_CONFIG_END
23
24machine_config_constructor psx_multitap_device::device_mconfig_additions() const
25{
26   return MACHINE_CONFIG_NAME( psx_multitap );
27}
28
29void psx_multitap_device::device_start()
30{
31   m_porta->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psx_multitap_device::ack), this));
32   m_portb->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psx_multitap_device::ack), this));
33   m_portc->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psx_multitap_device::ack), this));
34   m_portd->setup_ack_cb(psx_controller_port_device::void_cb(FUNC(psx_multitap_device::ack), this));
35   m_nextmode = false;
36}
37
38void psx_multitap_device::interface_pre_reset()
39{
40   m_activeport = -1;
41   m_singlemode = m_nextmode;
42   m_tapmc = false;
43   m_cack[0] = m_cack[1] = m_cack[2] = m_cack[3] = true;
44   memset(m_data, 0xff, sizeof(m_data));
45   m_porta->sel_w(false);
46   m_portb->sel_w(false);
47   m_portc->sel_w(false);
48   m_portd->sel_w(false);
49   m_porta->sel_w(true);
50   m_portb->sel_w(true);
51   m_portc->sel_w(true);
52   m_portd->sel_w(true);
53   device_psx_controller_interface::interface_pre_reset();
54}
55
56void psx_multitap_device::set_tx_line(bool tx, int port)
57{
58   psx_controller_port_device *dev;
59   switch(port)
60   {
61      default:
62      case 0:
63         dev = m_porta;
64         break;
65      case 1:
66         dev = m_portb;
67         break;
68      case 2:
69         dev = m_portc;
70         break;
71      case 3:
72         dev = m_portd;
73         break;
74   }
75   dev->clock_w(1);
76   dev->tx_w(tx);
77   dev->clock_w(0);
78}
79
80bool psx_multitap_device::get_rx_line(int port)
81{
82   psx_controller_port_device *dev;
83   switch(port)
84   {
85      default:
86      case 0:
87         dev = m_porta;
88         break;
89      case 1:
90         dev = m_portb;
91         break;
92      case 2:
93         dev = m_portc;
94         break;
95      case 3:
96         dev = m_portd;
97         break;
98   }
99   return dev->rx_r();
100}
101
102void psx_multitap_device::do_pad()
103{
104   bool tx = device_psx_controller_interface::m_owner->tx_r();
105
106   // we don't know which controller until after the first byte
107   if((m_singlemode || m_tapmc) && (m_count >= 1))
108   {
109      if((m_count == 2) && !m_bit && !m_tapmc)
110         m_nextmode = !tx;
111
112      set_tx_line(tx, m_activeport);
113      m_rx = get_rx_line(m_activeport);
114      m_bit = (m_bit + 1) % 8;
115      if(!m_bit)
116         m_count++;
117      return;
118   }
119
120   if(!m_count)
121   {
122      // first send the select byte to all devices until we know whether it's accessing
123      // a controller or memcard
124      if(!m_bit)
125      {
126         m_porta->sel_w(false);
127         m_portb->sel_w(false);
128         m_portc->sel_w(false);
129         m_portd->sel_w(false);
130      }
131      device_psx_controller_interface::do_pad();
132      set_tx_line(tx, 0);
133      set_tx_line(tx, 1);
134      set_tx_line(tx, 2);
135      set_tx_line(tx, 3);
136      if(!m_bit)
137      {
138         m_count = 1;
139         m_tapmc = m_memcard;
140         m_memcard = false; // make sure we still receive clocks
141         if(m_singlemode || m_tapmc)
142         {
143            m_activeport = (m_idata & 0xf) - 1;
144            m_porta->sel_w((m_activeport == 0) ? false : true);
145            m_portb->sel_w((m_activeport == 1) ? false : true);
146            m_portc->sel_w((m_activeport == 2) ? false : true);
147            m_portd->sel_w((m_activeport == 3) ? false : true);
148         }
149      }
150      return;
151   }
152   else if(m_count <= 2)
153      return device_psx_controller_interface::do_pad();
154   else if(m_count < 11)
155   {
156      if((m_count == 3) && !m_bit)
157         m_nextmode = !m_idata;
158
159      if((m_count < 5) && m_cack[0] && m_cack[1] && m_cack[2] && m_cack[3])
160         return; // no acks? hang up.
161
162      // all of the ports are polled here, port a is passed though.  the data
163      // from the other ports is stored and can be retrieved at a much higher clock rate
164      // don't poll a port that is inactive or done
165      if(!m_cack[0])
166      {
167         set_tx_line(tx, 0);
168         m_rx = m_porta->rx_r();
169      }
170      else
171      {
172         m_rx = true;
173         m_porta->sel_w(true);
174      }
175
176      if(!m_cack[1])
177      {
178         set_tx_line(tx, 1);
179         m_data[0][m_count - 3] &= ~(!m_portb->rx_r() << m_bit);
180      }
181      else
182         m_portb->sel_w(true);
183
184      if(!m_cack[2])
185      {
186         set_tx_line(tx, 2);
187         m_data[1][m_count - 3] &= ~(!m_portc->rx_r() << m_bit);
188      }
189      else
190         m_portc->sel_w(true);
191
192      if(!m_cack[3])
193      {
194         set_tx_line(tx, 3);
195         m_data[2][m_count - 3] &= ~(!m_portd->rx_r() << m_bit);
196      }
197      else
198         m_portd->sel_w(true);
199   }
200   else if(m_count < 19)
201      // send stored port b data
202      m_rx = ((m_data[0][m_count - 11] & (1 << m_bit)) ? 1 : 0);
203   else if(m_count < 27)
204      // send stored port c data
205      m_rx = ((m_data[1][m_count - 19] & (1 << m_bit)) ? 1 : 0);
206   else
207      // send stored port d data
208      m_rx = ((m_data[2][m_count - 27] & (1 << m_bit)) ? 1 : 0);
209
210   if(m_bit == 7)
211   {
212      // ports won't ack if they are done
213      m_cack[0] = m_cack[1] = m_cack[2] = m_cack[3] = true;
214      if(m_count < 11)
215         m_ack_timer->adjust(attotime::from_usec(12), 0); // give a bit of time for the ports to ack
216      else if(m_count < 35)
217         m_ack_timer->adjust(attotime::from_usec(10), 0);
218   }
219
220   m_bit = (m_bit + 1) % 8;
221   if(!m_bit)
222      m_count++;
223}
224
225bool psx_multitap_device::get_pad(int count, UINT8 *odata, UINT8 idata)
226{
227   if(!count)
228      *odata = 0x80;
229   else
230      *odata = 0x5a;
231   return true;
232}
233
234void psx_multitap_device::ack()
235{
236   if(m_activeport != -1)
237   {
238      switch(m_activeport)
239      {
240         case 0:
241            m_ack = m_porta->ack_r();
242            break;
243         case 1:
244            m_ack = m_portb->ack_r();
245            break;
246         case 2:
247            m_ack = m_portc->ack_r();
248            break;
249         case 3:
250            m_ack = m_portd->ack_r();
251            break;
252         default:
253            return;
254      }
255      device_psx_controller_interface::m_owner->ack();
256      return;
257   }
258   if(!m_porta->ack_r())
259      m_cack[0] = false;
260   if(!m_portb->ack_r())
261      m_cack[1] = false;
262   if(!m_portc->ack_r())
263      m_cack[2] = false;
264   if(!m_portd->ack_r())
265      m_cack[3] = false;
266}
Property changes on: trunk/src/mess/machine/psxmultitap.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/machine/psxmultitap.h
r0r22681
1#ifndef PSXMULTITAP_H_
2#define PSXMULTITAP_H_
3
4#include "machine/psxcport.h"
5
6SLOT_INTERFACE_EXTERN(psx_controllers_nomulti);
7
8class psx_multitap_device :   public device_t,
9                     public device_psx_controller_interface
10{
11public:
12   psx_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
13   virtual machine_config_constructor device_mconfig_additions() const;
14
15protected:
16   virtual void device_start();
17   virtual void device_stop() { device_psx_controller_interface::m_owner->disable_card(false); }
18   virtual void device_reset() { device_psx_controller_interface::m_owner->disable_card(true); }
19   virtual void device_config_complete() { m_shortname = "psx_multitap"; }
20   virtual void interface_pre_reset();
21
22private:
23   virtual bool get_pad(int count, UINT8 *odata, UINT8 idata);
24   virtual void do_pad();
25   void ack();
26   void set_tx_line(bool tx, int port);
27   bool get_rx_line(int port);
28
29   int m_activeport;
30   bool m_cack[4];
31   bool m_singlemode, m_nextmode, m_tapmc;
32   UINT8 m_data[3][8]; // port a is passed though
33   required_device<psx_controller_port_device> m_porta;
34   required_device<psx_controller_port_device> m_portb;
35   required_device<psx_controller_port_device> m_portc;
36   required_device<psx_controller_port_device> m_portd;
37};
38
39extern const device_type PSX_MULTITAP;
40
41#endif /* PSXMULTITAP_H_ */
Property changes on: trunk/src/mess/machine/psxmultitap.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/mess/mess.mak
r22680r22681
17711771   $(MESS_MACHINE)/psxcd.o     \
17721772   $(MESS_MACHINE)/psxcard.o   \
17731773   $(MESS_MACHINE)/psxanalog.o \
1774   $(MESS_MACHINE)/psxmultitap.o \
17741775   $(MESS_DRIVERS)/pockstat.o  \
17751776   $(MESS_DRIVERS)/smc777.o    \
17761777

Previous 199869 Revisions Next


© 1997-2024 The MAME Team