summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/megacdcd.h
blob: 9af07b75ab380765b76078ac18388283c9264947 (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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#include "sound/cdda.h"
#include "imagedev/chd_cd.h"


typedef device_delegate<void (int&, UINT8*, UINT16&, UINT16&)> segacd_dma_delegate;

typedef device_delegate<void (void)> interrupt_delegate;


#define READ_MAIN (0x0200)
#define READ_SUB  (0x0300)

#define REG_W_SBOUT  (0x0)
#define REG_W_IFCTRL (0x1)
#define REG_W_DBCL   (0x2)
#define REG_W_DBCH   (0x3)
#define REG_W_DACL   (0x4)
#define REG_W_DACH   (0x5)
#define REG_W_DTTRG  (0x6)
#define REG_W_DTACK  (0x7)
#define REG_W_WAL    (0x8)
#define REG_W_WAH    (0x9)
#define REG_W_CTRL0  (0xA)
#define REG_W_CTRL1  (0xB)
#define REG_W_PTL    (0xC)
#define REG_W_PTH    (0xD)
#define REG_W_CTRL2  (0xE)
#define REG_W_RESET  (0xF)

#define REG_R_COMIN  (0x0)
#define REG_R_IFSTAT (0x1)
#define REG_R_DBCL   (0x2)
#define REG_R_DBCH   (0x3)
#define REG_R_HEAD0  (0x4)
#define REG_R_HEAD1  (0x5)
#define REG_R_HEAD2  (0x6)
#define REG_R_HEAD3  (0x7)
#define REG_R_PTL    (0x8)
#define REG_R_PTH    (0x9)
#define REG_R_WAL    (0xa)
#define REG_R_WAH    (0xb)
#define REG_R_STAT0  (0xc)
#define REG_R_STAT1  (0xd)
#define REG_R_STAT2  (0xe)
#define REG_R_STAT3  (0xf)

#define CMD_STATUS   (0x0)
#define CMD_STOPALL  (0x1)
#define CMD_GETTOC   (0x2)
#define CMD_READ     (0x3)
#define CMD_SEEK     (0x4)
//                   (0x5)
#define CMD_STOP     (0x6)
#define CMD_RESUME   (0x7)
#define CMD_FF       (0x8)
#define CMD_RW       (0x9)
#define CMD_INIT     (0xa)
//                   (0xb)
#define CMD_CLOSE    (0xc)
#define CMD_OPEN     (0xd)
//                   (0xe)
//                   (0xf)


#define TOCCMD_CURPOS    (0x0)
#define TOCCMD_TRKPOS	 (0x1)
#define TOCCMD_CURTRK    (0x2)
#define TOCCMD_LENGTH    (0x3)
#define TOCCMD_FIRSTLAST (0x4)
#define TOCCMD_TRACKADDR (0x5)




#define SECTOR_SIZE (2352)

#define SET_CDD_DATA_MODE \
	CDD_CONTROL |= 0x0100; \

#define SET_CDD_AUDIO_MODE \
	CDD_CONTROL &= ~0x0100; \

#define STOP_CDC_READ \
	SCD_STATUS_CDC &= ~0x01; \

#define SET_CDC_READ \
	SCD_STATUS_CDC |= 0x01; \

#define SET_CDC_DMA \
	SCD_STATUS_CDC |= 0x08; \

#define STOP_CDC_DMA \
	SCD_STATUS_CDC &= ~0x08; \

#define SCD_READ_ENABLED \
	(SCD_STATUS_CDC & 1)

#define SCD_DMA_ENABLED \
	(SCD_STATUS_CDC & 0x08)

#define CLEAR_CDD_RESULT \
	CDD_MIN = CDD_SEC = CDD_FRAME = CDD_EXT = 0; \

#define CHECK_SCD_LV5_INTERRUPT \
	if (segacd_irq_mask & 0x20) \
	{ \
		machine.device(":segacd:segacd_68k")->execute().set_input_line(5, HOLD_LINE); \
	} \

#define CHECK_SCD_LV4_INTERRUPT \
	if (segacd_irq_mask & 0x10) \
	{ \
		machine.device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \
	} \

#define CHECK_SCD_LV4_INTERRUPT_A \
	if (segacd_irq_mask & 0x10) \
	{ \
		machine().device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \
	} \



#define CURRENT_TRACK_IS_DATA \
	(segacd.toc->tracks[SCD_CURTRK - 1].trktype != CD_TRACK_AUDIO) \


#define CDD_PLAYINGCDDA	0x0100
#define CDD_READY		0x0400
#define CDD_STOPPED		0x0900


#define MCFG_SEGACD_HACK_SET_CDC_DO_DMA( _class, _method) \
	lc89510_temp_device::set_CDC_Do_DMA(*device, segacd_dma_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); \

#define MCFG_SEGACD_HACK_SET_NEOCD \
	lc89510_temp_device::set_is_neoCD(*device, true); \

#define MCFG_SET_TYPE1_INTERRUPT_CALLBACK( _class, _method) \
	lc89510_temp_device::set_type1_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); \

#define MCFG_SET_TYPE2_INTERRUPT_CALLBACK( _class, _method) \
	lc89510_temp_device::set_type2_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); \

#define MCFG_SET_TYPE3_INTERRUPT_CALLBACK( _class, _method) \
	lc89510_temp_device::set_type3_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); \

/* neocd */

#define CD_FRAMES_MINUTE (60 * 75)
#define CD_FRAMES_SECOND (     75)
#define CD_FRAMES_PREGAP ( 2 * 75)

#define SEK_IRQSTATUS_NONE (0x0000)
#define SEK_IRQSTATUS_AUTO (0x2000)
#define SEK_IRQSTATUS_ACK  (0x1000)

#define LC89510_EXTERNAL_BUFFER_SIZE ((32 * 1024 * 2) + SECTOR_SIZE)

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

	// HACK for DMA handling
	segacd_dma_delegate segacd_dma_callback;
	interrupt_delegate type1_interrupt_callback;
	interrupt_delegate type2_interrupt_callback;
	interrupt_delegate type3_interrupt_callback;

	void Fake_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &dma_addrc, UINT16 &destination );
	static void set_CDC_Do_DMA(device_t &device,segacd_dma_delegate new_segacd_dma_callback);
	
	void dummy_interrupt_callback(void);
	static void set_type1_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback);
	static void set_type2_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback);
	static void set_type3_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback);


	static void set_is_neoCD(device_t &device, bool is_neoCD);


	// HACK for neoCD handling
	bool is_neoCD;


	struct segacd_t
	{
		cdrom_file	*cd;
		const cdrom_toc   *toc;
		UINT32 current_frame;
	};


	segacd_t segacd;

	UINT8    SCD_BUFFER[2560];

	UINT32   SCD_STATUS;
	UINT32   SCD_STATUS_CDC;
	INT32    SCD_CURLBA;
	UINT8    SCD_CURTRK;


	UINT16 CDC_DECODE;
	UINT16 CDC_REG0;
	UINT16 CDC_REG1;

	UINT8 CDC_BUFFER[LC89510_EXTERNAL_BUFFER_SIZE];


	UINT8 CDD_RX[10];
	UINT8 CDD_TX[10];

	UINT32 CDD_STATUS;
	UINT32 CDD_MIN;
	UINT32 CDD_SEC;
	UINT32 CDD_FRAME;
	UINT32 CDD_EXT;

	UINT16 CDD_CONTROL;

	INT16  CDD_DONE;

	inline int to_bcd(int val, bool byte);
	void set_data_audio_mode(void);
	void CDD_DoChecksum(void);
	bool CDD_Check_TX_Checksum(void);
	void CDD_Export(bool neocd_hack = false);
	void scd_ctrl_checks(running_machine& machine);
	void scd_advance_current_readpos(void);
	int Read_LBA_To_Buffer(running_machine& machine);
	void CDD_GetStatus(void);
	void CDD_Stop(running_machine &machine);
	void CDD_GetPos(void);
	void CDD_GetTrackPos(void);
	void CDD_GetTrack(void);
	void CDD_Length(void);
	void CDD_FirstLast(void);
	void CDD_GetTrackAdr(void);
	void CDD_GetTrackType(void);
	UINT32 getmsf_from_regs(void);
	void CDD_Play(running_machine &machine);
	void CDD_Seek(void);
	void CDD_Pause(running_machine &machine);
	void CDD_Resume(running_machine &machine);
	void CDD_FF(running_machine &machine);
	void CDD_RW(running_machine &machine);
	void CDD_Open(void);
	void CDD_Close(void);
	void CDD_Init(void);
	void CDD_Default(void);
	void CDD_Reset(void);
	void CDC_Reset(void);
	void lc89510_Reset(void);
	void CDC_End_Transfer(running_machine& machine);
	void CDC_Do_DMA(running_machine& machine, int rate);
	UINT16 CDC_Host_r(running_machine& machine, UINT16 type);
	UINT8 CDC_Reg_r(void);
	void CDC_Reg_w(UINT8 data);
	void CDD_Process(running_machine& machine, int reason);
	void CDD_Handle_TOC_Commands(void);
	bool CDD_Import(running_machine& machine);
	READ16_MEMBER( segacd_irq_mask_r );
	WRITE16_MEMBER( segacd_irq_mask_w );
	READ16_MEMBER( segacd_cdd_ctrl_r );
	WRITE16_MEMBER( segacd_cdd_ctrl_w );
	READ8_MEMBER( segacd_cdd_rx_r );
	WRITE8_MEMBER( segacd_cdd_tx_w );
	READ16_MEMBER( segacd_cdfader_r );
	WRITE16_MEMBER( segacd_cdfader_w );

	void reset_cd(void);

	WRITE16_MEMBER( segacd_cdc_mode_address_w );
	READ16_MEMBER( segacd_cdc_mode_address_r );
	WRITE16_MEMBER( segacd_cdc_data_w );
	READ16_MEMBER( segacd_cdc_data_r );
	READ16_MEMBER( cdc_data_sub_r );
	READ16_MEMBER( cdc_data_main_r );

	TIMER_DEVICE_CALLBACK_MEMBER( segacd_access_timer_callback );

	UINT16 get_segacd_irq_mask(void) { return segacd_irq_mask; }
	UINT16 segacd_irq_mask;
	cdda_device* m_cdda;

	/* NeoCD */
	UINT16 nff0002;
	UINT16 nff0016;


	INT32 LC8951RegistersR[16];
	INT32 LC8951RegistersW[16];



	bool bNeoCDCommsClock;

	INT32 NeoCDCommsWordCount;

	INT32 NeoCD_StatusHack;




	void NeoCDCommsControl(UINT8 clock, UINT8 send);
	void LC8951UpdateHeader();
	char* LC8915InitTransfer(int NeoCDDMACount);
	void LC8915EndTransfer();

	void neocd_cdd_tx_w(UINT8 data);
	UINT8 neocd_cdd_rx_r();
	void NeoCDCommsReset();


	UINT16 nff0016_r(void);
	void nff0016_set(UINT16 wordValue);
	void nff0002_set(UINT16 wordValue);

protected:
	virtual void device_start();
	virtual void device_reset();
	virtual machine_config_constructor device_mconfig_additions() const;
private:


};

extern const device_type LC89510_TEMP;