summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/psxcport.h
blob: f3b3a3ed4747ec0cf8ef21fdb1393bd70d270fa2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#pragma once

#ifndef __PSXCPORT_H__
#define __PSXCPORT_H__

#include "cpu/psx/siodev.h"
#include "machine/psxcard.h"

#define MCFG_PSX_CTRL_PORT_ADD(_tag, _slot_intf, _def_slot, _def_inp) \
	MCFG_DEVICE_ADD(_tag, PSX_CONTROLLER_PORT, 0) \
	MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp, false)

SLOT_INTERFACE_EXTERN(psx_controllers);

extern const device_type PSXCONTROLLERPORTS;
extern const device_type PSX_CONTROLLER_PORT;
extern const device_type PSX_STANDARD_CONTROLLER;

class psx_controller_port_device;

class device_psx_controller_interface : public device_slot_card_interface
{
public:
	device_psx_controller_interface(const machine_config &mconfig, device_t &device);
	virtual ~device_psx_controller_interface();

	void clock_w(bool state) { if(m_clock && !m_sel && !state && !m_memcard) do_pad(); m_clock = state; }
	void sel_w(bool state);

	bool rx_r() { return m_rx; }
	bool ack_r() { return m_ack; }

protected:
	virtual void interface_pre_reset();
	virtual void interface_pre_start();

	enum
	{
		QUERY_PAD_STATE = 0x42,
		CONFIG_MODE = 0x43,
	};

private:
	virtual bool get_pad(int count, UINT8 *odata, UINT8 idata) = 0;
	virtual void do_pad();
	void ack_timer(void *ptr, int param);

	UINT8 m_odata;
	UINT8 m_idata;
	int m_bit;
	int m_count;
	bool m_memcard;

	bool m_clock;
	bool m_sel;
	bool m_ack;
	bool m_rx;

	emu_timer *m_ack_timer;
	psx_controller_port_device *m_owner;
};

class psx_standard_controller_device :	public device_t,
										public device_psx_controller_interface
{
public:
	psx_standard_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	virtual ioport_constructor device_input_ports() const;

protected:
	virtual void device_start() { }
	virtual void device_config_complete() { m_shortname = "psx_standard_controller"; }
private:
	virtual bool get_pad(int count, UINT8 *odata, UINT8 idata);

	required_ioport m_pad0;
	required_ioport m_pad1;
};

class psxcontrollerports_device : public psxsiodev_device
{
public:
	psxcontrollerports_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	void ack();

protected:
	void device_start();

private:
	virtual void data_in(int data, int mask);

	psx_controller_port_device *m_port0;
	psx_controller_port_device *m_port1;
};

class psx_controller_port_device :	public device_t,
									public device_slot_interface
{
public:
	psx_controller_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	virtual machine_config_constructor device_mconfig_additions() const;

	typedef delegate<void ()> void_cb;
	void ack() { if(!ack_cb.isnull()) ack_cb(); }
	void setup_ack_cb(void_cb cb) { ack_cb = cb; }

	DECLARE_WRITE_LINE_MEMBER(tx_w) { m_tx = state; }
	DECLARE_WRITE_LINE_MEMBER(sel_w) { if(m_dev) m_dev->sel_w(state); m_card->sel_w(state); }
	DECLARE_WRITE_LINE_MEMBER(clock_w) { if(m_dev) m_dev->clock_w(state); m_card->clock_w(state); }

	DECLARE_READ_LINE_MEMBER(rx_r) { return (m_dev?m_dev->rx_r():true) && m_card->rx_r(); }
	DECLARE_READ_LINE_MEMBER(ack_r) { return (m_dev?m_dev->ack_r():true) && m_card->ack_r(); }
	DECLARE_READ_LINE_MEMBER(tx_r) { return m_tx; }

protected:
	virtual void device_start() {}
	virtual void device_reset() { m_tx = true; }
	virtual void device_config_complete();

private:
	void_cb ack_cb;
	bool m_tx;

	device_psx_controller_interface *m_dev;
	required_device<psxcard_device> m_card;
};
#endif