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
|
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
/**********************************************************************
Sega Mark III "Paddle Control" emulation
Release data from the Sega Retro project:
Year: 1987 Country/region: JP Model code: HPD-200
Notes:
The main chip contained in the device is labeled 315-5243.
The Paddle Control was only released in Japan. To work with the device,
paddle games need to detect the system region as Japanese, else they switch
to a different mode that uses the TH line as output to select which nibble
of the X axis will be read. This other mode is similar to how the US Sports
Pad works, so on an Export system, paddle games are somewhat playable with
that device, though it needs to be used inverted and the trackball needs to
be moved slowly, else the software for the paddle think it's moving backward.
**********************************************************************/
#include "emu.h"
#include "paddle.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device, "sms_paddle", "Sega SMS Paddle")
// time interval not verified
// Player 2 of Galactic Protector is the most sensible to this timming.
#define PADDLE_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/100)
CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r )
{
uint8_t data = m_paddle_x->read();
if (m_read_state)
data >>= 4;
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~data;
}
READ_LINE_MEMBER( sms_paddle_device::tr_pin_r )
{
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~m_read_state;
}
static INPUT_PORTS_START( sms_paddle )
PORT_START("CTRL_PORT")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, rldu_pins_r, nullptr) // R,L,D,U
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER( DEVICE_SELF, sms_paddle_device, tr_pin_r ) // TR
PORT_START("PADDLE_X") // Paddle knob
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor sms_paddle_device::device_input_ports() const
{
return INPUT_PORTS_NAME( sms_paddle );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// sms_paddle_device - constructor
//-------------------------------------------------
sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_PADDLE, tag, owner, clock),
device_sms_control_port_interface(mconfig, *this),
m_paddle_pins(*this, "CTRL_PORT"),
m_paddle_x(*this, "PADDLE_X"),
m_read_state(0),
m_interval(PADDLE_INTERVAL)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void sms_paddle_device::device_start()
{
m_start_time = machine().time();
save_item(NAME(m_start_time));
save_item(NAME(m_read_state));
}
//-------------------------------------------------
// sms_peripheral_r - paddle read
//-------------------------------------------------
uint8_t sms_paddle_device::peripheral_r()
{
int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
m_read_state = num_intervals & 1;
return m_paddle_pins->read();
}
|