summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/pce.cpp
blob: aa9ba6112d57cc3b2cae3c083cb7bffd1b040eec (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
// license:BSD-3-Clause
// copyright-holders:Charles MacDonald, Wilbert Pol, Angelo Salese
/************************************************************

PC Engine CD HW notes:

TODO:
- Dragon Ball Z: ADPCM dies after the first upload;
- Dragon Slayer - The Legend of Heroes: black screen;
- Mirai Shonen Conan: dies at new game selection;
- Snatcher: black screen after Konami logo, tries set up CD-DA
            while transferring data?
- Steam Heart's: needs transfer ready irq to get past the
                 gameplay hang, don't know exactly when it should fire
- Steam Heart's: bad ADPCM irq, dialogue is cutted due of it;

=============================================================

CD Interface Register 0x00 - CDC status
x--- ---- busy signal
-x-- ---- request signal
---x ---- cd signal
---- x--- i/o signal

CD Interface Register 0x03 - BRAM lock / CD status
-x-- ---- acknowledge signal
--x- ---- done signal
---x ---- bram signal
---- x--- ADPCM 2
---- -x-- ADPCM 1
---- --x- CDDA left/right speaker select

CD Interface Register 0x05 - CD-DA Volume low 8-bit port

CD Interface Register 0x06 - CD-DA Volume high 8-bit port

CD Interface Register 0x07 - BRAM unlock / CD status
x--- ---- Enables BRAM

CD Interface Register 0x0c - ADPCM status
x--- ---- ADPCM is reading data
---- x--- ADPCM playback (0) stopped (1) currently playing
---- -x-- pending ADPCM data write
---- ---x ADPCM playback (1) stopped (0) currently playing

CD Interface Register 0x0d - ADPCM address control
x--- ---- ADPCM reset
-x-- ---- ADPCM play
--x- ---- ADPCM repeat
---x ---- ADPCM set length
---- x--- ADPCM set read address
---- --xx ADPCM set write address
(note: some games reads bit 5 and wants it to be low otherwise they hangs, surely NOT an ADPCM repeat flag read because it doesn't make sense)

CD Interface Register 0x0e - ADPCM playback rate

CD Interface Register 0x0f - ADPCM fade in/out register
---- xxxx command setting:
0x00 ADPCM/CD-DA Fade-in
0x01 CD-DA fade-in
0x08 CD-DA fade-out (short) ADPCM fade-in
0x09 CD-DA fade-out (long)
0x0a ADPCM fade-out (long)
0x0c CD-DA fade-out (short) ADPCM fade-in
0x0d CD-DA fade-out (short)
0x0e ADPCM fade-out (short)

*************************************************************/

#include "emu.h"
#include "cpu/h6280/h6280.h"
#include "includes/pce.h"


/* joystick related data*/

#define JOY_CLOCK   0x01
#define JOY_RESET   0x02



void pce_state::init_mess_pce()
{
	m_io_port_options = PCE_JOY_SIG | CONST_SIG;
}

void pce_state::init_tg16()
{
	m_io_port_options = TG_16_JOY_SIG | CONST_SIG;
}

void pce_state::init_sgx()
{
	m_io_port_options = PCE_JOY_SIG | CONST_SIG;
}

MACHINE_START_MEMBER(pce_state,pce)
{
	if (m_cd)
		m_cd->late_setup();

	// saving is only partially supported: it should be fine with cart games
	// OTOH CD states are saved but not correctly restored!
	save_item(NAME(m_io_port_options));
	save_item(NAME(m_acard));
	save_item(NAME(m_joystick_port_select));
	save_item(NAME(m_joystick_data_select));
	save_item(NAME(m_joy_6b_packet));
}

MACHINE_RESET_MEMBER(pce_state,mess_pce)
{
	for (auto & elem : m_joy_6b_packet)
		elem = 0;

	/* Note: Arcade Card BIOS contents are the same as System 3, only internal HW differs.
	   We use a category to select between modes (some games can be run in either S-CD or A-CD modes) */
	m_acard = m_a_card->read() & 1;

	if (m_cartslot->get_type() == PCE_CDSYS3J)
	{
		m_sys3_card = 1;
		m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x080000, 0x087fff, read8_delegate(*this, FUNC(pce_state::pce_cd_acard_wram_r)), write8_delegate(*this, FUNC(pce_state::pce_cd_acard_wram_w)));
	}

	if (m_cartslot->get_type() == PCE_CDSYS3U)
	{
		m_sys3_card = 3;
		m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x080000, 0x087fff, read8_delegate(*this, FUNC(pce_state::pce_cd_acard_wram_r)), write8_delegate(*this, FUNC(pce_state::pce_cd_acard_wram_w)));
	}
}

/* todo: how many input ports does the PCE have? */
WRITE8_MEMBER(pce_state::mess_pce_joystick_w)
{
	int joy_i;
	uint8_t joy_type = m_joy_type->read();

	/* bump counter on a low-to-high transition of bit 1 */
	if ((!m_joystick_data_select) && (data & JOY_CLOCK))
	{
		m_joystick_port_select = (m_joystick_port_select + 1) & 0x07;
	}

	/* do we want buttons or direction? */
	m_joystick_data_select = data & JOY_CLOCK;

	/* clear counter if bit 2 is set */
	if (data & JOY_RESET)
	{
		m_joystick_port_select = 0;

		for (joy_i = 0; joy_i < 5; joy_i++)
		{
			if (((joy_type >> (joy_i*2)) & 3) == 2)
				m_joy_6b_packet[joy_i] ^= 1;
		}
	}
}

READ8_MEMBER(pce_state::mess_pce_joystick_r)
{
	uint8_t joy_type = m_joy_type->read();
	uint8_t ret, data;

	if (m_joystick_port_select <= 4)
	{
		switch ((joy_type >> (m_joystick_port_select*2)) & 3)
		{
			case 0: //2-buttons pad
				data = m_joy[m_joystick_port_select]->read();
				break;
			case 2: //6-buttons pad
				/*
				Two packets:
				1st packet: directions + I, II, Run, Select
				2nd packet: 6 buttons "header" (high 4 bits active low) + III, IV, V, VI
				Note that six buttons pad just doesn't work with (almost?) every single 2-button-only games, it's really just an after-thought and it is like this
				on real HW.
				*/
				data = m_joy6b[m_joystick_port_select]->read() >> (m_joy_6b_packet[m_joystick_port_select]*8);
				break;
			default:
				data = 0xff;
				break;
		}
	}
	else
		data = 0xff;


	if (m_joystick_data_select)
		data >>= 4;

	ret = (data & 0x0f) | m_io_port_options;
#ifdef UNIFIED_PCE
	ret &= ~0x40;
#endif

	return (ret);
}


WRITE8_MEMBER(pce_state::pce_cd_intf_w)
{
	m_cd->update();

	if (offset & 0x200 && m_sys3_card && m_acard) // route Arcade Card handling ports
		return m_cd->acard_w(space, offset, data);

	m_cd->intf_w(space, offset, data);

	m_cd->update();
}

READ8_MEMBER(pce_state::pce_cd_intf_r)
{
	m_cd->update();

	if (offset & 0x200 && m_sys3_card && m_acard) // route Arcade Card handling ports
		return m_cd->acard_r(space, offset);

	if ((offset & 0xc0) == 0xc0 && m_sys3_card) //System 3 Card header handling
	{
		switch (offset & 0xcf)
		{
			case 0xc1: return 0xaa;
			case 0xc2: return 0x55;
			case 0xc3: return 0x00;
			case 0xc5: return (m_sys3_card & 2) ? 0x55 : 0xaa;
			case 0xc6: return (m_sys3_card & 2) ? 0xaa : 0x55;
			case 0xc7: return 0x03;
		}
	}

	return m_cd->intf_r(space, offset);
}


READ8_MEMBER(pce_state::pce_cd_acard_wram_r)
{
	return pce_cd_intf_r(space, 0x200 | (offset & 0x6000) >> 9);
}

WRITE8_MEMBER(pce_state::pce_cd_acard_wram_w)
{
	pce_cd_intf_w(space, 0x200 | (offset & 0x6000) >> 9, data);
}