summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/devcb.h
blob: a0c6834e3b8551f06dcea930bb358359a6f438a0 (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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/***************************************************************************

    devcb.h

    Device callback interface helpers.

    Copyright Nicola Salmoria and the MAME Team.
    Visit http://mamedev.org for licensing and usage restrictions.

****************************************************************************

    These functions are used to adapt multiple read/write handler types
    to be used with device I/O. In general, a device is expected to
    declare its desired callback type, and these functions allow other
    callback types to be adapted appropriately.

    The desired callback types currently supported include:

        read_line_device_func:  (device)
        write_line_device_func: (device, data)
        read8_device_func:      (device, offset)
        write8_device_func:     (device, offset, data)

    The adapted callback types supported are:

        input port              (port)
        cpu input line          (cpu input line)
        read_line_device_func:  (device)
        write_line_device_func: (device, data)
        read8_device_func:      (device, offset)
        write8_device_func:     (device, offset, data)
        read8_space_func:       (space, offset)
        write8_space_func:      (space, offset, data)

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

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef __DEVCB_H__
#define __DEVCB_H__


/***************************************************************************
    CONSTANTS
***************************************************************************/

#define DEVCB_TYPE_NULL				(0)
#define DEVCB_TYPE_SELF				(1)
#define DEVCB_TYPE_INPUT			(2)
#define DEVCB_TYPE_DEVICE			(3)
#define DEVCB_TYPE_MEMORY(space)	(4 + (space))
#define DEVCB_TYPE_CPU_LINE(line)	(4 + ADDRESS_SPACES + (line))



/***************************************************************************
    MACROS
***************************************************************************/

// static template for a read_line stub function that calls through a given READ_LINE_MEMBER
template<class _Class, int (_Class::*_Function)()>
int devcb_line_stub(device_t *device)
{
	_Class *target = downcast<_Class *>(device);
	return (target->*_Function)();
}

// static template for a read8 stub function that calls through a given READ8_MEMBER
template<class _Class, UINT8 (_Class::*_Function)(address_space &, offs_t, UINT8)>
UINT8 devcb_stub(device_t *device, offs_t offset)
{
	_Class *target = downcast<_Class *>(device);
	return (target->*_Function)(*device->machine->m_nonspecific_space, offset, 0xff);
}

// static template for a write_line stub function that calls through a given WRITE_LINE_MEMBER
template<class _Class, void (_Class::*_Function)(int state)>
void devcb_line_stub(device_t *device, int state)
{
	_Class *target = downcast<_Class *>(device);
	(target->*_Function)(state);
}

// static template for a write8 stub function that calls through a given WRITE8_MEMBER
template<class _Class, void (_Class::*_Function)(address_space &, offs_t, UINT8, UINT8)>
void devcb_stub(device_t *device, offs_t offset, UINT8 data)
{
	_Class *target = downcast<_Class *>(device);
	(target->*_Function)(*device->machine->m_nonspecific_space, offset, data, 0xff);
}

#define DEVCB_NULL							{ DEVCB_TYPE_NULL }

/* standard line or read/write handlers with the calling device passed */
#define DEVCB_LINE(func)						{ DEVCB_TYPE_SELF, NULL, (func), NULL, NULL }
#define DEVCB_LINE_MEMBER(func)					{ DEVCB_TYPE_SELF, NULL, &devcb_line_stub<cls, &cls::memb>, NULL, NULL }
#define DEVCB_LINE_GND							{ DEVCB_TYPE_SELF, NULL, devcb_line_gnd_r, NULL, NULL }
#define DEVCB_LINE_VCC							{ DEVCB_TYPE_SELF, NULL, devcb_line_vcc_r, NULL, NULL }
#define DEVCB_HANDLER(func)						{ DEVCB_TYPE_SELF, NULL, NULL, (func), NULL }
#define DEVCB_MEMBER(cls,memb)					{ DEVCB_TYPE_SELF, NULL, NULL, &devcb_stub<cls, &cls::memb>, NULL }

/* line or read/write handlers for another device */
#define DEVCB_DEVICE_LINE(tag,func)				{ DEVCB_TYPE_DEVICE, tag, (func), NULL, NULL }
#define DEVCB_DEVICE_LINE_MEMBER(tag,cls,memb)	{ DEVCB_TYPE_DEVICE, tag, &devcb_line_stub<cls, &cls::memb>, NULL, NULL }
#define DEVCB_DEVICE_HANDLER(tag,func)			{ DEVCB_TYPE_DEVICE, tag, NULL, (func), NULL }
#define DEVCB_DEVICE_MEMBER(tag,cls,memb)		{ DEVCB_TYPE_DEVICE, tag, NULL, &devcb_stub<cls, &cls::memb>, NULL }

/* read/write handlers for a given CPU's address space */
#define DEVCB_MEMORY_HANDLER(cpu,space,func) { DEVCB_TYPE_MEMORY(ADDRESS_SPACE_##space), (cpu), NULL, NULL, (func) }

/* read handlers for an I/O port by tag */
#define DEVCB_INPUT_PORT(tag)				{ DEVCB_TYPE_INPUT, (tag), NULL, NULL, NULL }

/* write handlers for a CPU input line */
#define DEVCB_CPU_INPUT_LINE(tag,line)		{ DEVCB_TYPE_CPU_LINE(line), (tag), NULL, NULL, NULL }


/* macros for defining read_line/write_line functions */
#define READ_LINE_DEVICE_HANDLER(name)		int  name(ATTR_UNUSED device_t *device)
#define WRITE_LINE_DEVICE_HANDLER(name) 	void name(ATTR_UNUSED device_t *device, ATTR_UNUSED int state)

#define DECLARE_READ_LINE_MEMBER(name)		int  name()
#define READ_LINE_MEMBER(name)				int  name()
#define DECLARE_WRITE_LINE_MEMBER(name) 	void name(ATTR_UNUSED int state)
#define WRITE_LINE_MEMBER(name)				void name(ATTR_UNUSED int state)

/* macros for inline device handler initialization */

#define MDRV_DEVICE_CONFIG_DEVCB_GENERIC(_access, _struct, _entry, _tag, _type, _linefunc, _devfunc, _spacefunc) \
	MDRV_DEVICE_CONFIG_DATA32(_struct, _entry .type, DEVCB_TYPE_DEVICE) \
	MDRV_DEVICE_CONFIG_DATAPTR(_struct, _entry .tag, _tag) \
	MDRV_DEVICE_CONFIG_DATAPTR(_struct, _entry . _access ## line, _linefunc) \
	MDRV_DEVICE_CONFIG_DATAPTR(_struct, _entry . _access ## device, _devfunc) \
	MDRV_DEVICE_CONFIG_DATAPTR(_struct, _entry .  _access ## space, _spacefunc)

#define MDRV_DEVICE_CONFIG_READ_LINE(_struct, _entry, _tag, _func) MDRV_DEVICE_CONFIG_DEVCB_GENERIC(read, _struct, _entry, _tag, DEVCB_TYPE_DEVICE, _func, NULL, NULL)
#define MDRV_DEVICE_CONFIG_WRITE_LINE(_struct, _entry, _tag, _func) MDRV_DEVICE_CONFIG_DEVCB_GENERIC(write, _struct, _entry, _tag, DEVCB_TYPE_DEVICE, _func, NULL, NULL)

#define MDRV_DEVICE_CONFIG_READ_HANDLER(_struct, _entry, _tag, _func) MDRV_DEVICE_CONFIG_DEVCB_GENERIC(read, _struct, _entry, _tag, DEVCB_TYPE_DEVICE, NULL, _func, NULL)
#define MDRV_DEVICE_CONFIG_WRITE_HANDLER(_struct, _entry, _tag, _func) MDRV_DEVICE_CONFIG_DEVCB_GENERIC(write, _struct, _entry, _tag, DEVCB_TYPE_DEVICE, NULL, _func, NULL)



/***************************************************************************
    TYPE DEFINITIONS
***************************************************************************/

/* forward declarations */
class device_config;


/* static structure used for device configuration when the desired callback type is a read_line_device_func */
typedef struct _devcb_read_line devcb_read_line;
struct _devcb_read_line
{
	UINT32					type;			/* one of the special DEVCB_TYPE values */
	const char *			tag;			/* tag of target, where appropriate */
	read_line_device_func	readline;		/* read line function */
	read8_device_func		readdevice;		/* read device function */
	read8_space_func		readspace;		/* read space function */
};

typedef struct _devcb_resolved_read_line devcb_resolved_read_line;
struct _devcb_resolved_read_line
{
	const void *			target;			/* target object */
	read_line_device_func	read;			/* read line function */
	const void *			realtarget;		/* real target object for stubs */
	union
	{
		read8_device_func	readdevice;
		read8_space_func	readspace;
	} real;									/* real read function for stubs */
};


/* static structure used for device configuration when the desired callback type is a write_line_device_func */
typedef struct _devcb_write_line devcb_write_line;
struct _devcb_write_line
{
	UINT32					type;			/* one of the special DEVCB_TYPE values */
	const char *			tag;			/* tag of target, where appropriate */
	write_line_device_func	writeline;		/* write line function */
	write8_device_func		writedevice;	/* write device function */
	write8_space_func		writespace;		/* write space function */
};

typedef struct _devcb_resolved_write_line devcb_resolved_write_line;
struct _devcb_resolved_write_line
{
	const void *			target;			/* target object */
	write_line_device_func	write;			/* write line function */
	const void *			realtarget;		/* real target object for stubs */
	union
	{
		write8_device_func	writedevice;
		write8_space_func	writespace;
		int					writeline;
	} real;									/* real write function for stubs */
};


/* static structure used for device configuration when the desired callback type is a read8_device_func */
typedef struct _devcb_read8 devcb_read8;
struct _devcb_read8
{
	UINT32					type;			/* one of the special DEVCB_TYPE values */
	const char *			tag;			/* tag of target, where appropriate */
	read_line_device_func	readline;		/* read line function */
	read8_device_func		readdevice;		/* read device function */
	read8_space_func		readspace;		/* read space function */
};

typedef struct _devcb_resolved_read8 devcb_resolved_read8;
struct _devcb_resolved_read8
{
	const void *			target;			/* target object */
	read8_device_func		read;			/* read function */
	const void *			realtarget;		/* real target object for stubs */
	union
	{
		read8_device_func	readdevice;
		read8_space_func	readspace;
		read_line_device_func readline;
	} real;									/* real read function for stubs */
};


/* static structure used for device configuration when the desired callback type is a write8_device_func */
typedef struct _devcb_write8 devcb_write8;
struct _devcb_write8
{
	UINT32					type;			/* one of the special DEVCB_TYPE values */
	const char *			tag;			/* tag of target, where appropriate */
	write_line_device_func	writeline;		/* write line function */
	write8_device_func		writedevice;	/* write device function */
	write8_space_func		writespace;		/* write space function */
};

typedef struct _devcb_resolved_write8 devcb_resolved_write8;
struct _devcb_resolved_write8
{
	const void *			target;			/* target object */
	write8_device_func		write;			/* write function */
	const void *			realtarget;		/* real target object for stubs */
	union
	{
		write8_device_func	writedevice;
		write8_space_func	writespace;
		write_line_device_func writeline;
	} real;									/* real write function for stubs */
};



/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/


/* ----- static-to-live conversion ----- */

/* convert a static read line definition to a live definition */
void devcb_resolve_read_line(devcb_resolved_read_line *resolved, const devcb_read_line *config, device_t *device);

/* convert a static write line definition to a live definition */
void devcb_resolve_write_line(devcb_resolved_write_line *resolved, const devcb_write_line *config, device_t *device);

/* convert a static 8-bit read definition to a live definition */
void devcb_resolve_read8(devcb_resolved_read8 *resolved, const devcb_read8 *config, device_t *device);

/* convert a static 8-bit write definition to a live definition */
void devcb_resolve_write8(devcb_resolved_write8 *resolved, const devcb_write8 *config, device_t *device);



/***************************************************************************
    INLINE FUNCTIONS
***************************************************************************/

/*-------------------------------------------------
    devcb_call_read_line - call through a
    resolved read_line handler
-------------------------------------------------*/

INLINE int devcb_call_read_line(const devcb_resolved_read_line *resolved)
{
	return (resolved->read != NULL) ? (*resolved->read)((device_t *)resolved->target) : 0;
}


/*-------------------------------------------------
    devcb_call_read8 - call through a
    resolved read8 handler
-------------------------------------------------*/

INLINE int devcb_call_read8(const devcb_resolved_read8 *resolved, offs_t offset)
{
	return (resolved->read != NULL) ? (*resolved->read)((device_t *)resolved->target, offset) : 0;
}


/*-------------------------------------------------
    devcb_call_write_line - call through a
    resolved write_line handler
-------------------------------------------------*/

INLINE void devcb_call_write_line(const devcb_resolved_write_line *resolved, int state)
{
	if (resolved->write != NULL)
		(*resolved->write)((device_t *)resolved->target, state);
}


/*-------------------------------------------------
    devcb_call_write8 - call through a
    resolved write8 handler
-------------------------------------------------*/

INLINE void devcb_call_write8(const devcb_resolved_write8 *resolved, offs_t offset, UINT8 data)
{
	if (resolved->write != NULL)
		(*resolved->write)((device_t *)resolved->target, offset, data);
}

/*-------------------------------------------------
    devcb_line_gnd_r - input tied to GND
-------------------------------------------------*/

INLINE READ_LINE_DEVICE_HANDLER( devcb_line_gnd_r )
{
	return 0;
}

/*-------------------------------------------------
    devcb_line_vcc_r - input tied to Vcc
-------------------------------------------------*/

INLINE READ_LINE_DEVICE_HANDLER( devcb_line_vcc_r )
{
	return 1;
}

#endif	/* __DEVCB_H__ */