1 /***************************************************************************
2 
3   cpuintrf.c
4 
5   Don't you love MS-DOS 8+3 names? That stands for CPU interface.
6   Functions needed to interface the CPU emulator with the other parts of
7   the emulation.
8 
9 ***************************************************************************/
10 
11 /*#include <signal.h>*/
12 #include "driver.h"
13 #include "timer.h"
14 #include "state.h"
15 #include "hiscore.h"
16 
17 #ifdef WANT_LIBCO
18 extern int libco_quit;
19 #endif
20 
21 #if (HAS_Z80)
22 #include "cpu/z80/z80.h"
23 #endif
24 #if (HAS_DRZ80)
25 #include "cpu/z80_drz80/drz80_z80.h"
26 #endif
27 #if (HAS_Z80GB)
28 #include "cpu/z80gb/z80gb.h"
29 #endif
30 #if (HAS_8080 || HAS_8085A)
31 #include "cpu/i8085/i8085.h"
32 #endif
33 #if (HAS_M6502 || HAS_M65C02 || HAS_M65SC02 || HAS_M6510 || HAS_M6510T || HAS_M7501 || HAS_M8502 || HAS_N2A03)
34 #include "cpu/m6502/m6502.h"
35 #endif
36 #if (HAS_M4510)
37 #include "cpu/m6502/m4510.h"
38 #endif
39 #if (HAS_M65CE02)
40 #include "cpu/m6502/m65ce02.h"
41 #endif
42 #if (HAS_M6509)
43 #include "cpu/m6502/m6509.h"
44 #endif
45 #if (HAS_H6280)
46 #include "cpu/h6280/h6280.h"
47 #endif
48 #if (HAS_I86)
49 #include "cpu/i86/i86intf.h"
50 #endif
51 #if (HAS_I88)
52 #include "cpu/i86/i88intf.h"
53 #endif
54 #if (HAS_I186)
55 #include "cpu/i86/i186intf.h"
56 #endif
57 #if (HAS_I188)
58 #include "cpu/i86/i188intf.h"
59 #endif
60 #if (HAS_I286)
61 #include "cpu/i86/i286intf.h"
62 #endif
63 #if (HAS_V20 || HAS_V30 || HAS_V33)
64 #include "cpu/nec/necintrf.h"
65 #endif
66 #if (HAS_ARMNEC)
67 #include "cpu/nec_armnec/armnecintrf.h"
68 #endif
69 #if (HAS_I8035 || HAS_I8039 || HAS_I8048 || HAS_N7751)
70 #include "cpu/i8039/i8039.h"
71 #endif
72 #if (HAS_M6800 || HAS_M6801 || HAS_M6802 || HAS_M6803 || HAS_M6808 || HAS_HD63701)
73 #include "cpu/m6800/m6800.h"
74 #endif
75 #if (HAS_M6805 || HAS_M68705 || HAS_HD63705)
76 #include "cpu/m6805/m6805.h"
77 #endif
78 #if (HAS_HD6309 || HAS_M6809)
79 #include "cpu/m6809/m6809.h"
80 #endif
81 #if (HAS_KONAMI)
82 #include "cpu/konami/konami.h"
83 #endif
84 #if (HAS_M68000 || defined HAS_M68010 || HAS_M68020 || HAS_M68EC020)
85 #include "cpu/m68000/m68000.h"
86 #endif
87 #if (HAS_CYCLONE)
88 #include "cpu/m68000_cyclone/c68000.h"
89 #endif
90 #if (HAS_T11)
91 #include "cpu/t11/t11.h"
92 #endif
93 #if (HAS_S2650)
94 #include "cpu/s2650/s2650.h"
95 #endif
96 #if (HAS_TMS34010)
97 #include "cpu/tms34010/tms34010.h"
98 #endif
99 #if (HAS_TMS9900) || (HAS_TMS9940) || (HAS_TMS9980) || (HAS_TMS9985) \
100 	|| (HAS_TMS9989) || (HAS_TMS9995) || (HAS_TMS99105A) || (HAS_TMS99110A)
101 #include "cpu/tms9900/tms9900.h"
102 #endif
103 #if (HAS_Z8000)
104 #include "cpu/z8000/z8000.h"
105 #endif
106 #if (HAS_TMS320C10)
107 #include "cpu/tms32010/tms32010.h"
108 #endif
109 #if (HAS_CCPU)
110 #include "cpu/ccpu/ccpu.h"
111 #endif
112 #if (HAS_PDP1)
113 #include "cpu/pdp1/pdp1.h"
114 #endif
115 #if (HAS_ADSP2100) || (HAS_ADSP2105)
116 #include "cpu/adsp2100/adsp2100.h"
117 #endif
118 #if (HAS_MIPS)
119 #include "cpu/mips/mips.h"
120 #endif
121 #if (HAS_SC61860)
122 #include "cpu/sc61860/sc61860.h"
123 #endif
124 #if (HAS_ARM)
125 #include "cpu/arm/arm.h"
126 #endif
127 
128 
129 /* these are triggers sent to the timer system for various interrupt events */
130 #define TRIGGER_TIMESLICE		-1000
131 #define TRIGGER_INT 			-2000
132 #define TRIGGER_YIELDTIME		-3000
133 #define TRIGGER_SUSPENDTIME 	-4000
134 
135 #define VERBOSE 0
136 
137 #define SAVE_STATE_TEST 0
138 #if VERBOSE
139 #define LOG(x)	logerror x
140 #else
141 #define LOG(x)
142 #endif
143 
144 #ifdef _MSC_VER
145 __declspec(align(32))
146 #endif
147 struct cpuinfo
148 {
149 	struct cpu_interface *intf; 	/* pointer to the interface functions */
150 	int iloops; 					/* number of interrupts remaining this frame */
151 	int totalcycles;				/* total CPU cycles executed */
152 	int vblankint_countdown;		/* number of vblank callbacks left until we interrupt */
153 	int vblankint_multiplier;		/* number of vblank callbacks per interrupt */
154 	void *vblankint_timer;			/* reference to elapsed time counter */
155 	timer_tm vblankint_period;		/* timing period of the VBLANK interrupt */
156 	void *timedint_timer;			/* reference to this CPU's timer */
157 	timer_tm timedint_period; 		/* timing period of the timed interrupt */
158 	void *context;					/* dynamically allocated context buffer */
159 	int save_context;				/* need to context switch this CPU? yes or no */
160 }
161 #ifndef _MSC_VER
162 __attribute__ ((__aligned__ (32)))
163 #endif
164 ;
165 
166 static struct cpuinfo cpu[MAX_CPU];
167 
168 static int activecpu,totalcpu;
169 static int cycles_running;	/* number of cycles that the CPU emulation was requested to run */
170 					/* (needed by cpu_getfcount) */
171 static int have_to_reset;
172 
173 static int interrupt_enable[MAX_CPU];
174 static int interrupt_vector[MAX_CPU];
175 
176 static int irq_line_state[MAX_CPU * MAX_IRQ_LINES];
177 static int irq_line_vector[MAX_CPU * MAX_IRQ_LINES];
178 
179 static int watchdog_counter;
180 
181 static void *vblank_timer;
182 static int vblank_countdown;
183 static int vblank_multiplier;
184 static timer_tm vblank_period;
185 
186 static void *refresh_timer;
187 static timer_tm refresh_period;
188 
189 static void *timeslice_timer;
190 static timer_tm timeslice_period;
191 
192 static timer_tm scanline_period;
193 
194 static int usres; /* removed from cpu_run and made global */
195 static int vblank;
196 static int current_frame;
197 
198 static void cpu_generate_interrupt(int cpunum, int (*func)(void), int num);
199 static void cpu_vblankintcallback(int param);
200 static void cpu_timedintcallback(int param);
201 static void cpu_internal_interrupt(int cpunum, int type);
202 static void cpu_manualnmicallback(int param);
203 static void cpu_manualirqcallback(int param);
204 static void cpu_internalintcallback(int param);
205 static void cpu_manualintcallback(int param);
206 static void cpu_clearintcallback(int param);
207 static void cpu_resetcallback(int param);
208 static void cpu_haltcallback(int param);
209 static void cpu_timeslicecallback(int param);
210 static void cpu_vblankreset(void);
211 static void cpu_vblankcallback(int param);
212 static void cpu_updatecallback(int param);
213 static timer_tm cpu_computerate(int value);
214 static void cpu_inittimers(void);
215 
216 
217 /* default irq callback handlers */
218 static int cpu_0_irq_callback(int irqline);
219 static int cpu_1_irq_callback(int irqline);
220 static int cpu_2_irq_callback(int irqline);
221 static int cpu_3_irq_callback(int irqline);
222 static int cpu_4_irq_callback(int irqline);
223 static int cpu_5_irq_callback(int irqline);
224 static int cpu_6_irq_callback(int irqline);
225 static int cpu_7_irq_callback(int irqline);
226 
227 /* and a list of them for indexed access */
228 static int (*cpu_irq_callbacks[MAX_CPU])(int) = {
229 	cpu_0_irq_callback, cpu_1_irq_callback, cpu_2_irq_callback, cpu_3_irq_callback,
230 	cpu_4_irq_callback, cpu_5_irq_callback, cpu_6_irq_callback, cpu_7_irq_callback
231 };
232 
233 /* and a list of driver interception hooks */
234 static int (*drv_irq_callbacks[MAX_CPU])(int) = { NULL, };
235 
236 /* Dummy interfaces for non-CPUs */
237 static void Dummy_reset(void *param);
238 static void Dummy_exit(void);
239 static int Dummy_execute(int cycles);
240 //static void Dummy_burn(int cycles);
241 static unsigned Dummy_get_context(void *regs);
242 static void Dummy_set_context(void *regs);
243 static unsigned Dummy_get_pc(void);
244 static void Dummy_set_pc(unsigned val);
245 static unsigned Dummy_get_sp(void);
246 static void Dummy_set_sp(unsigned val);
247 static unsigned Dummy_get_reg(int regnum);
248 static void Dummy_set_reg(int regnum, unsigned val);
249 static void Dummy_set_nmi_line(int state);
250 static void Dummy_set_irq_line(int irqline, int state);
251 static void Dummy_set_irq_callback(int (*callback)(int irqline));
252 static int Dummy_ICount;
253 static const char *Dummy_info(void *context, int regnum);
254 static unsigned Dummy_dasm(char *buffer, unsigned pc);
255 
256 /* Convenience macros - not in cpuintrf.h because they shouldn't be used by everyone */
257 #define RESET(index)					((*cpu[index].intf->reset)(Machine->drv->cpu[index].reset_param))
258 #define EXECUTE(index,cycles)			((*cpu[index].intf->execute)(cycles))
259 #define GETCONTEXT(index,context)		((*cpu[index].intf->get_context)(context))
260 #define SETCONTEXT(index,context)		((*cpu[index].intf->set_context)(context))
261 #define GETCYCLETBL(index,which)		((*cpu[index].intf->get_cycle_table)(which))
262 #define SETCYCLETBL(index,which,cnts)	((*cpu[index].intf->set_cycle_table)(which,cnts))
263 #define GETPC(index)                    ((*cpu[index].intf->get_pc)())
264 #define SETPC(index,val)				((*cpu[index].intf->set_pc)(val))
265 #define GETSP(index)					((*cpu[index].intf->get_sp)())
266 #define SETSP(index,val)				((*cpu[index].intf->set_sp)(val))
267 #define GETREG(index,regnum)			((*cpu[index].intf->get_reg)(regnum))
268 #define SETREG(index,regnum,value)		((*cpu[index].intf->set_reg)(regnum,value))
269 #define SETNMILINE(index,state) 		((*cpu[index].intf->set_nmi_line)(state))
270 #define SETIRQLINE(index,line,state)	((*cpu[index].intf->set_irq_line)(line,state))
271 #define SETIRQCALLBACK(index,callback)	((*cpu[index].intf->set_irq_callback)(callback))
272 #define INTERNAL_INTERRUPT(index,type)	if( cpu[index].intf->internal_interrupt ) ((*cpu[index].intf->internal_interrupt)(type))
273 #define CPUINFO(index,context,regnum)	((*cpu[index].intf->cpu_info)(context,regnum))
274 #define CPUDASM(index,buffer,pc)		((*cpu[index].intf->cpu_dasm)(buffer,pc))
275 #define ICOUNT(index)					(*cpu[index].intf->icount)
276 #define INT_TYPE_NONE(index)			(cpu[index].intf->no_int)
277 #define INT_TYPE_IRQ(index) 			(cpu[index].intf->irq_int)
278 #define INT_TYPE_NMI(index) 			(cpu[index].intf->nmi_int)
279 #define READMEM(index,offset)			((*cpu[index].intf->memory_read)(offset))
280 #define WRITEMEM(index,offset,data) 	((*cpu[index].intf->memory_write)(offset,data))
281 #define SET_OP_BASE(index,pc)			((*cpu[index].intf->set_op_base)(pc))
282 
283 #define CPU_TYPE(index) 				(Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK)
284 #define CPU_AUDIO(index)				(Machine->drv->cpu[index].cpu_type & CPU_AUDIO_CPU)
285 
286 #define IFC_INFO(cpu,context,regnum)	((cpuintf[cpu].cpu_info)(context,regnum))
287 
288 /* most CPUs use this macro */
289 #define CPU0(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
290 	{																			   \
291 		CPU_##cpu,																   \
292 		name##_reset, name##_exit, name##_execute, NULL,						   \
293 		name##_get_context, name##_set_context, NULL, NULL, 					   \
294 		name##_get_pc, name##_set_pc,											   \
295 		name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg,			   \
296 		name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback,		   \
297 		NULL,NULL,NULL, name##_info, name##_dasm,								   \
298 		nirq, dirq, &name##_ICount, oc, i0, i1, i2,							   \
299 		cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem,				   \
300 		shift, bits, CPU_IS_##endian, align, maxinst,							   \
301 		ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM 							   \
302 	}
303 
304 /* CPUs which have _burn, _state_save and _state_load functions */
305 #define CPU1(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM)   \
306 	{																			   \
307 		CPU_##cpu,																   \
308 		name##_reset, name##_exit, name##_execute,								   \
309 		name##_burn,															   \
310 		name##_get_context, name##_set_context, 								   \
311 		name##_get_cycle_table, name##_set_cycle_table, 						   \
312 		name##_get_pc, name##_set_pc,											   \
313 		name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg,			   \
314 		name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback,		   \
315 		NULL,name##_state_save,name##_state_load, name##_info, name##_dasm, 	   \
316 		nirq, dirq, &name##_ICount, oc, i0, i1, i2,							   \
317 		cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem,				   \
318 		shift, bits, CPU_IS_##endian, align, maxinst,							   \
319 		ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM 							   \
320 	}
321 
322 /* CPUs which have the _internal_interrupt function */
323 #define CPU2(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM)   \
324 	{																			   \
325 		CPU_##cpu,																   \
326 		name##_reset, name##_exit, name##_execute,								   \
327 		NULL,																	   \
328 		name##_get_context, name##_set_context, NULL, NULL, 					   \
329         name##_get_pc, name##_set_pc,                                              \
330 		name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg,			   \
331 		name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback,		   \
332 		name##_internal_interrupt,NULL,NULL, name##_info, name##_dasm,			   \
333 		nirq, dirq, &name##_ICount, oc, i0, i1, i2,							   \
334 		cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem,				   \
335 		shift, bits, CPU_IS_##endian, align, maxinst,							   \
336 		ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM 							   \
337 	}																			   \
338 
339 /* alternative CPU0 for ICount refs */
340 #define CPU3(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
341 {																			   \
342 	CPU_##cpu,																   \
343 	name##_reset, name##_exit, name##_execute, NULL,						   \
344 	name##_get_context, name##_set_context, NULL, NULL, 					   \
345 	name##_get_pc, name##_set_pc,											   \
346 	name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg,			   \
347 	name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback,		   \
348 		NULL,NULL,NULL, name##_info, name##_dasm,								   \
349 	nirq, dirq, NULL, oc, i0, i1, i2,							   \
350 	cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem,				   \
351 	shift, bits, CPU_IS_##endian, align, maxinst,							   \
352 	ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM 							   \
353 }
354 
355 /* alternative CPU1 for ICount refs */
356 #define CPU4(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM)   \
357 {																			   \
358 	CPU_##cpu,																   \
359 	name##_reset, name##_exit, name##_execute,								   \
360 	name##_burn,															   \
361 	name##_get_context, name##_set_context, 								   \
362 	name##_get_cycle_table, name##_set_cycle_table, 						   \
363 	name##_get_pc, name##_set_pc,											   \
364 	name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg,			   \
365 	name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback,		   \
366 	NULL,name##_state_save,name##_state_load, name##_info, name##_dasm, 	   \
367 	nirq, dirq, NULL, oc, i0, i1, i2,							   \
368 	cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem,				   \
369 	shift, bits, CPU_IS_##endian, align, maxinst,							   \
370 	ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM 							   \
371 }
372 
373 
374 
375 /* warning the ordering must match the one of the enum in driver.h! */
376 struct cpu_interface cpuintf[] =
377 {
378 	CPU0(DUMMY,    Dummy,	 1,  0,1.00,0,				   -1,			   -1,			   16,	  0,16,LE,1, 1,16	),
379 #if (HAS_Z80)
380 	CPU1(Z80,	   z80, 	 1,255,1.00,Z80_IGNORE_INT,    Z80_IRQ_INT,    Z80_NMI_INT,    16,	  0,16,LE,1, 4,16	),
381 #endif
382 #if (HAS_DRZ80)
383 	CPU4(DRZ80,	   drz80, 	 1,255,1.00,DRZ80_IGNORE_INT,    DRZ80_IRQ_INT,    DRZ80_NMI_INT,    16,	  0,16,LE,1, 4,16	),
384 #endif
385 #if (HAS_Z80GB)
386 	CPU0(Z80GB,    z80gb,	 5,255,1.00,Z80GB_IGNORE_INT,  0,			   1,			   16,	  0,16,LE,1, 4,16	),
387 #endif
388 #if (HAS_8080)
389 	CPU0(8080,	   i8080,	 4,255,1.00,I8080_NONE, 	   I8080_INTR,	   I8080_TRAP,	   16,	  0,16,LE,1, 3,16	),
390 #endif
391 #if (HAS_8085A)
392 	CPU0(8085A,    i8085,	 4,255,1.00,I8085_NONE, 	   I8085_INTR,	   I8085_TRAP,	   16,	  0,16,LE,1, 3,16	),
393 #endif
394 #if (HAS_M6502)
395 	CPU0(M6502,    m6502,	 1,  0,1.00,M6502_INT_NONE,    M6502_INT_IRQ,  M6502_INT_NMI,  16,	  0,16,LE,1, 3,16	),
396 #endif
397 #if (HAS_M65C02)
398 	CPU0(M65C02,   m65c02,	 1,  0,1.00,M65C02_INT_NONE,   M65C02_INT_IRQ, M65C02_INT_NMI, 16,	  0,16,LE,1, 3,16	),
399 #endif
400 #if (HAS_M65SC02)
401 	CPU0(M65SC02,  m65sc02,  1,  0,1.00,M65SC02_INT_NONE,  M65SC02_INT_IRQ,M65SC02_INT_NMI,16,	  0,16,LE,1, 3,16	),
402 #endif
403 #if (HAS_M65CE02)
404 	CPU0(M65CE02,  m65ce02,  1,  0,1.00,M65CE02_INT_NONE,  M65CE02_INT_IRQ,M65CE02_INT_NMI,16,	  0,16,LE,1, 3,16	),
405 #endif
406 #if (HAS_M6509)
407 	CPU0(M6509,    m6509,	 1,  0,1.00,M6509_INT_NONE,    M6509_INT_IRQ,  M6509_INT_NMI,  20,	  0,20,LE,1, 3,20	),
408 #endif
409 #if (HAS_M6510)
410 	CPU0(M6510,    m6510,	 1,  0,1.00,M6510_INT_NONE,    M6510_INT_IRQ,  M6510_INT_NMI,  16,	  0,16,LE,1, 3,16	),
411 #endif
412 #if (HAS_M6510T)
413 	CPU0(M6510T,   m6510t,	 1,  0,1.00,M6510T_INT_NONE,   M6510T_INT_IRQ, M6510T_INT_NMI, 16,	  0,16,LE,1, 3,16	),
414 #endif
415 #if (HAS_M7501)
416 	CPU0(M7501,    m7501,	 1,  0,1.00,M7501_INT_NONE,    M7501_INT_IRQ,  M7501_INT_NMI,  16,	  0,16,LE,1, 3,16	),
417 #endif
418 #if (HAS_M8502)
419 	CPU0(M8502,    m8502,	 1,  0,1.00,M8502_INT_NONE,    M8502_INT_IRQ,  M8502_INT_NMI,  16,	  0,16,LE,1, 3,16	),
420 #endif
421 #if (HAS_N2A03)
422 	CPU0(N2A03,    n2a03,	 1,  0,1.00,N2A03_INT_NONE,    N2A03_INT_IRQ,  N2A03_INT_NMI,  16,	  0,16,LE,1, 3,16	),
423 #endif
424 #if (HAS_M4510)
425 	CPU0(M4510,    m4510,	 1,  0,1.00,M4510_INT_NONE,    M4510_INT_IRQ,  M4510_INT_NMI,  20,	  0,20,LE,1, 3,20	),
426 #endif
427 #if (HAS_H6280)
428 	CPU0(H6280,    h6280,	 3,  0,1.00,H6280_INT_NONE,    -1,			   H6280_INT_NMI,  21,	  0,21,LE,1, 3,21	),
429 #endif
430 #if (HAS_I86)
431 	CPU0(I86,	   i86, 	 1,  0,1.00,I86_INT_NONE,	   -1000,		   I86_NMI_INT,    20,	  0,20,LE,1, 5,20	),
432 #endif
433 #if (HAS_I88)
434 	CPU0(I88,	   i88, 	 1,  0,1.00,I88_INT_NONE,	   -1000,		   I88_NMI_INT,    20,	  0,20,LE,1, 5,20	),
435 #endif
436 #if (HAS_I186)
437 	CPU0(I186,	   i186,	 1,  0,1.00,I186_INT_NONE,	   -1000,		   I186_NMI_INT,   20,	  0,20,LE,1, 5,20	),
438 #endif
439 #if (HAS_I188)
440 	CPU0(I188,	   i188,	 1,  0,1.00,I188_INT_NONE,	   -1000,		   I188_NMI_INT,   20,	  0,20,LE,1, 5,20	),
441 #endif
442 #if (HAS_I286)
443 	CPU0(I286,	   i286,	 1,  0,1.00,I286_INT_NONE,	   -1000,		   I286_NMI_INT,   24,	  0,24,LE,1, 5,24	),
444 #endif
445 #if (HAS_V20)
446 	CPU0(V20,	   v20, 	 1,  0,1.00,NEC_INT_NONE,	   -1000,		   NEC_NMI_INT,    20,	  0,20,LE,1, 5,20	),
447 #endif
448 #if (HAS_V30)
449 	CPU0(V30,	   v30, 	 1,  0,1.00,NEC_INT_NONE,	   -1000,		   NEC_NMI_INT,    20,	  0,20,LE,1, 5,20	),
450 #endif
451 #if (HAS_V33)
452 	CPU0(V33,	   v33, 	 1,  0,1.20,NEC_INT_NONE,	   -1000,		   NEC_NMI_INT,    20,	  0,20,LE,1, 5,20	),
453 #endif
454 #if (HAS_ARMNEC)
455 	CPU0(ARMV30,   armv30, 	 1,  0,1.00,NEC_INT_NONE,	   -1000,		   NEC_NMI_INT,    20,	  0,20,LE,1, 5,20	),
456 	CPU0(ARMV33,   armv33, 	 1,  0,1.20,NEC_INT_NONE,	   -1000,		   NEC_NMI_INT,    20,	  0,20,LE,1, 5,20	),
457 #endif
458 #if (HAS_I8035)
459 	CPU0(I8035,    i8035,	 1,  0,1.00,I8035_IGNORE_INT,  I8035_EXT_INT,  -1,			   16,	  0,16,LE,1, 2,16	),
460 #endif
461 #if (HAS_I8039)
462 	CPU0(I8039,    i8039,	 1,  0,1.00,I8039_IGNORE_INT,  I8039_EXT_INT,  -1,			   16,	  0,16,LE,1, 2,16	),
463 #endif
464 #if (HAS_I8048)
465 	CPU0(I8048,    i8048,	 1,  0,1.00,I8048_IGNORE_INT,  I8048_EXT_INT,  -1,			   16,	  0,16,LE,1, 2,16	),
466 #endif
467 #if (HAS_N7751)
468 	CPU0(N7751,    n7751,	 1,  0,1.00,N7751_IGNORE_INT,  N7751_EXT_INT,  -1,			   16,	  0,16,LE,1, 2,16	),
469 #endif
470 #if (HAS_M6800)
471 	CPU0(M6800,    m6800,	 1,  0,1.00,M6800_INT_NONE,    M6800_INT_IRQ,  M6800_INT_NMI,  16,	  0,16,BE,1, 4,16	),
472 #endif
473 #if (HAS_M6801)
474 	CPU0(M6801,    m6801,	 1,  0,1.00,M6801_INT_NONE,    M6801_INT_IRQ,  M6801_INT_NMI,  16,	  0,16,BE,1, 4,16	),
475 #endif
476 #if (HAS_M6802)
477 	CPU0(M6802,    m6802,	 1,  0,1.00,M6802_INT_NONE,    M6802_INT_IRQ,  M6802_INT_NMI,  16,	  0,16,BE,1, 4,16	),
478 #endif
479 #if (HAS_M6803)
480 	CPU0(M6803,    m6803,	 1,  0,1.00,M6803_INT_NONE,    M6803_INT_IRQ,  M6803_INT_NMI,  16,	  0,16,BE,1, 4,16	),
481 #endif
482 #if (HAS_M6808)
483 	CPU0(M6808,    m6808,	 1,  0,1.00,M6808_INT_NONE,    M6808_INT_IRQ,  M6808_INT_NMI,  16,	  0,16,BE,1, 4,16	),
484 #endif
485 #if (HAS_HD63701)
486 	CPU0(HD63701,  hd63701,  1,  0,1.00,HD63701_INT_NONE,  HD63701_INT_IRQ,HD63701_INT_NMI,16,	  0,16,BE,1, 4,16	),
487 #endif
488 #if (HAS_NSC8105)
489 	CPU0(NSC8105,  nsc8105,  1,  0,1.00,NSC8105_INT_NONE,  NSC8105_INT_IRQ,NSC8105_INT_NMI,16,	  0,16,BE,1, 4,16	),
490 #endif
491 #if (HAS_M6805)
492 	CPU0(M6805,    m6805,	 1,  0,1.00,M6805_INT_NONE,    M6805_INT_IRQ,  -1,			   16,	  0,11,BE,1, 3,16	),
493 #endif
494 #if (HAS_M68705)
495 	CPU0(M68705,   m68705,	 1,  0,1.00,M68705_INT_NONE,   M68705_INT_IRQ, -1,			   16,	  0,11,BE,1, 3,16	),
496 #endif
497 #if (HAS_HD63705)
498 	CPU0(HD63705,  hd63705,  8,  0,1.00,HD63705_INT_NONE,  HD63705_INT_IRQ,-1,			   16,	  0,16,BE,1, 3,16	),
499 #endif
500 #if (HAS_HD6309)
501 	CPU0(HD6309,   hd6309,	 2,  0,1.00,HD6309_INT_NONE,   HD6309_INT_IRQ, HD6309_INT_NMI, 16,	  0,16,BE,1, 4,16	),
502 #endif
503 #if (HAS_M6809)
504 	CPU0(M6809,    m6809,	 2,  0,1.00,M6809_INT_NONE,    M6809_INT_IRQ,  M6809_INT_NMI,  16,	  0,16,BE,1, 4,16	),
505 #endif
506 #if (HAS_KONAMI)
507 	CPU0(KONAMI,   konami,	 2,  0,1.00,KONAMI_INT_NONE,   KONAMI_INT_IRQ, KONAMI_INT_NMI, 16,	  0,16,BE,1, 4,16	),
508 #endif
509 #if (HAS_M68000)
510 	CPU0(M68000,   m68000,	 8, -1,1.00,MC68000_INT_NONE,  -1,			   -1,			   24bew, 0,24,BE,2,10,24BEW),
511 #endif
512 #if (HAS_CYCLONE)
513 	CPU3(CYCLONE,   cyclone, 8, -1,1.00,cyclone_INT_NONE,  -1,			   -1,			   24bew, 0,24,BE,2,10,24BEW),
514 #endif
515 #if (HAS_M68010)
516 	CPU0(M68010,   m68010,	 8, -1,1.00,MC68010_INT_NONE,  -1,			   -1,			   24bew, 0,24,BE,2,10,24BEW),
517 #endif
518 #if (HAS_M68EC020)
519 	CPU0(M68EC020, m68ec020, 8, -1,1.00,MC68EC020_INT_NONE,-1,			   -1,			   24bew, 0,24,BE,2,10,24BEW),
520 #endif
521 #if (HAS_M68020)
522 	CPU0(M68020,   m68020,	 8, -1,1.00,MC68020_INT_NONE,  -1,			   -1,			   24bew, 0,24,BE,2,10,24BEW),
523 #endif
524 #if (HAS_T11)
525 	CPU0(T11,	   t11, 	 4,  0,1.00,T11_INT_NONE,	   -1,			   -1,			   16lew, 0,16,LE,2, 6,16LEW),
526 #endif
527 #if (HAS_S2650)
528 	CPU0(S2650,    s2650,	 2,  0,1.00,S2650_INT_NONE,    -1,			   -1,			   16,	  0,15,LE,1, 3,16	),
529 #endif
530 #if (HAS_TMS34010)
531 	CPU2(TMS34010, tms34010, 2,  0,1.00,TMS34010_INT_NONE, TMS34010_INT1,  -1,			   29,	  3,29,LE,2,10,29	),
532 #endif
533 #if (HAS_TMS9900)
534 	CPU0(TMS9900,  tms9900,  1,  0,1.00,TMS9900_NONE,	   -1,			   -1,			   16bew, 0,16,BE,2, 6,16BEW),
535 #endif
536 #if (HAS_TMS9940)
537 	CPU0(TMS9940,  tms9940,  1,  0,1.00,TMS9940_NONE,	   -1,			   -1,			   16bew, 0,16,BE,2, 6,16BEW),
538 #endif
539 #if (HAS_TMS9980)
540 	CPU0(TMS9980,  tms9980a, 1,  0,1.00,TMS9980A_NONE,	   -1,			   -1,			   16,	  0,16,BE,1, 6,16	),
541 #endif
542 #if (HAS_TMS9985)
543 	CPU0(TMS9985,  tms9985,  1,  0,1.00,TMS9985_NONE,	   -1,			   -1,			   16,	  0,16,BE,1, 6,16	),
544 #endif
545 #if (HAS_TMS9989)
546 	CPU0(TMS9989,  tms9989,  1,  0,1.00,TMS9989_NONE,	   -1,			   -1,			   16,	  0,16,BE,1, 6,16	),
547 #endif
548 #if (HAS_TMS9995)
549 	CPU0(TMS9995,  tms9995,  1,  0,1.00,TMS9995_NONE,	   -1,			   -1,			   16,	  0,16,BE,1, 6,16	),
550 #endif
551 #if (HAS_TMS99105A)
552 	CPU0(TMS99105A,tms99105a,1,  0,1.00,TMS99105A_NONE,    -1,			   -1,			   16bew, 0,16,BE,2, 6,16BEW),
553 #endif
554 #if (HAS_TMS99110A)
555 	CPU0(TMS99110A,tms99110a,1,  0,1.00,TMS99110A_NONE,    -1,			   -1,			   16bew, 0,16,BE,2, 6,16BEW),
556 #endif
557 #if (HAS_Z8000)
558 	CPU0(Z8000,    z8000,	 2,  0,1.00,Z8000_INT_NONE,    Z8000_NVI,	   Z8000_NMI,	   16bew, 0,16,BE,2, 6,16BEW),
559 #endif
560 #if (HAS_TMS320C10)
561 	CPU0(TMS320C10,tms320c10,2,  0,1.00,TMS320C10_INT_NONE,-1,			   -1,			   16,	 -1,16,BE,2, 4,16	),
562 #endif
563 #if (HAS_CCPU)
564 	CPU0(CCPU,	   ccpu,	 2,  0,1.00,0,				   -1,			   -1,			   16,	  0,15,LE,1, 3,16	),
565 #endif
566 #if (HAS_PDP1)
567 	CPU0(PDP1,	   pdp1,	 0,  0,1.00,0,				   -1,			   -1,			   16,	  0,18,LE,1, 3,16	),
568 #endif
569 #if (HAS_ADSP2100)
570 /* IMO we should rename all *_ICount to *_icount - ie. no mixed case */
571 #define adsp2100_ICount adsp2100_icount
572 	CPU0(ADSP2100, adsp2100, 4,  0,1.00,ADSP2100_INT_NONE, -1,			   -1,			   16lew,-1,14,LE,2, 4,16LEW),
573 #endif
574 #if (HAS_ADSP2105)
575 /* IMO we should rename all *_ICount to *_icount - ie. no mixed case */
576 #define adsp2105_ICount adsp2105_icount
577 	CPU0(ADSP2105, adsp2105, 4,  0,1.00,ADSP2105_INT_NONE, -1,			   -1,			   16lew,-1,14,LE,2, 4,16LEW),
578 #endif
579 #if (HAS_MIPS)
580 	CPU0(MIPS,	   mips,	 8, -1,1.00,MIPS_INT_NONE,	   MIPS_INT_NONE,  MIPS_INT_NONE,  32lew, 0,32,LE,4, 4,32LEW),
581 #endif
582 #if (HAS_SC61860)
583 	#define sc61860_ICount sc61860_icount
584 	CPU0(SC61860,  sc61860,  1,  0,1.00,-1,				   -1,			   -1,			   16,    0,16,BE,1, 4,16	),
585 #endif
586 #if (HAS_ARM)
587 	CPU0(ARM,	   arm, 	 2,  0,1.00,ARM_INT_NONE,	   ARM_FIRQ,	   ARM_IRQ, 	   26lew, 0,26,LE,4, 4,26LEW),
588 #endif
589 };
590 
cpu_init(void)591 void cpu_init(void)
592 {
593 	int i;
594 
595 	/* Verify the order of entries in the cpuintf[] array */
596 	for( i = 0; i < CPU_COUNT; i++ )
597 	{
598 		if( cpuintf[i].cpu_num != i )
599 		{
600 logerror("CPU #%d [%s] wrong ID %d: check enum CPU_... in src/driver.h!\n", i, cputype_name(i), cpuintf[i].cpu_num);
601 			exit(1);
602 		}
603 	}
604 
605 /* hacks for our two custom CPUs */
606 #ifdef HAS_DRZ80
607 	cpuintf[CPU_DRZ80].icount = &drz80_ICount;
608 #endif
609 
610 #ifdef HAS_CYCLONE
611 	cpuintf[CPU_CYCLONE].icount = &cyclone_ICount;
612 #endif
613 
614 	/* count how many CPUs we have to emulate */
615 	totalcpu = 0;
616 
617 	while (totalcpu < MAX_CPU)
618 	{
619 		if( CPU_TYPE(totalcpu) == CPU_DUMMY ) break;
620 		totalcpu++;
621 	}
622 
623 	/* zap the CPU data structure */
624 	memset(cpu, 0, sizeof(cpu));
625 
626 	/* Set up the interface functions */
627 	for (i = 0; i < MAX_CPU; i++)
628 		cpu[i].intf = &cpuintf[CPU_TYPE(i)];
629 
630 	/* reset the timer system */
631 	timer_init();
632 	timeslice_timer = refresh_timer = vblank_timer = NULL;
633 }
634 
cpu_run(void)635 void cpu_run(void)
636 {
637 	int i;
638 
639 	/* determine which CPUs need a context switch */
640 	for (i = 0; i < totalcpu; i++)
641 	{
642 		int j, size;
643 
644 		/* allocate a context buffer for the CPU */
645 		size = GETCONTEXT(i,NULL);
646 		if( size == 0 )
647 		{
648 			/* That can't really be true */
649 logerror("CPU #%d claims to need no context buffer!\n", i);
650 			/*raise( SIGABRT );*/
651 		}
652 
653 		cpu[i].context = malloc( size );
654 		if( cpu[i].context == NULL )
655 		{
656 			/* That's really bad :( */
657 logerror("CPU #%d failed to allocate context buffer (%d bytes)!\n", i, size);
658 			/*raise( SIGABRT );*/
659 		}
660 
661 		/* Zap the context buffer */
662 		memset(cpu[i].context, 0, size );
663 
664 
665 		/* Save if there is another CPU of the same type */
666 		cpu[i].save_context = 0;
667 
668 		for (j = 0; j < totalcpu; j++)
669 			if ( i != j && !strcmp(cpunum_core_file(i),cpunum_core_file(j)) )
670 				cpu[i].save_context = 1;
671 
672 		for( j = 0; j < MAX_IRQ_LINES; j++ )
673 		{
674 			irq_line_state[i * MAX_IRQ_LINES + j] = CLEAR_LINE;
675 			irq_line_vector[i * MAX_IRQ_LINES + j] = cpuintf[CPU_TYPE(i)].default_vector;
676 		}
677 	}
678 
679 reset:
680 	/* read hi scores information from hiscore.dat */
681 	hs_open(Machine->gamedrv->name);
682 	hs_init();
683 
684 	/* initialize the various timers (suspends all CPUs at startup) */
685 	cpu_inittimers();
686 	watchdog_counter = -1;
687 
688 	/* reset sound chips */
689 	sound_reset();
690 
691 	/* enable all CPUs (except for audio CPUs if the sound is off) */
692 	for (i = 0; i < totalcpu; i++)
693 	{
694 		if (!CPU_AUDIO(i) || Machine->sample_rate != 0)
695 		{
696 			timer_suspendcpu(i, 0, SUSPEND_REASON_RESET);
697 		}
698 		else
699 		{
700 			timer_suspendcpu(i, 1, SUSPEND_REASON_DISABLE);
701 		}
702 	}
703 
704 	have_to_reset = 0;
705 	vblank = 0;
706 
707 logerror("Machine reset\n");
708 
709 	/* start with interrupts enabled, so the generic routine will work even if */
710 	/* the machine doesn't have an interrupt enable port */
711 	for (i = 0;i < MAX_CPU;i++)
712 	{
713 		interrupt_enable[i] = 1;
714 		interrupt_vector[i] = 0xff;
715         /* Reset any driver hooks into the IRQ acknowledge callbacks */
716         drv_irq_callbacks[i] = NULL;
717 	}
718 
719 	/* do this AFTER the above so init_machine() can use cpu_halt() to hold the */
720 	/* execution of some CPUs, or disable interrupts */
721 	if (Machine->drv->init_machine) (*Machine->drv->init_machine)();
722 
723 	/* reset each CPU */
724 	for (i = 0; i < totalcpu; i++)
725 	{
726 		/* swap memory contexts and reset */
727 		memorycontextswap(i);
728 		if (cpu[i].save_context) SETCONTEXT(i, cpu[i].context);
729 		activecpu = i;
730 		RESET(i);
731 
732 		/* Set the irq callback for the cpu */
733 		SETIRQCALLBACK(i,cpu_irq_callbacks[i]);
734 
735 
736 		/* save the CPU context if necessary */
737 		if (cpu[i].save_context) GETCONTEXT (i, cpu[i].context);
738 
739 		/* reset the total number of cycles */
740 		cpu[i].totalcycles = 0;
741 	}
742 
743 	/* reset the globals */
744 	cpu_vblankreset();
745 	current_frame = 0;
746 
747 	/* loop until the user quits */
748 	usres = 0;
749 	while (usres == 0)
750 	{
751 		int cpunum;
752 #ifdef WANT_LIBCO
753                if(libco_quit==1)usres=1;
754 #endif
755 		/* was machine_reset() called? */
756 		if (have_to_reset)
757 		{
758 #ifdef MESS
759 			if (Machine->drv->stop_machine) (*Machine->drv->stop_machine)();
760 #endif
761 			goto reset;
762 		}
763 		profiler_mark(PROFILER_EXTRA);
764 
765 #if SAVE_STATE_TEST
766 		{
767 			if( keyboard_pressed_memory(KEYCODE_S) )
768 			{
769 				void *s = state_create(Machine->gamedrv->name);
770 				if( s )
771 				{
772 					for( cpunum = 0; cpunum < totalcpu; cpunum++ )
773 					{
774 						activecpu = cpunum;
775 						memorycontextswap(activecpu);
776 						if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
777 						/* make sure any bank switching is reset */
778 						SET_OP_BASE(activecpu, GETPC(activecpu));
779 						if( cpu[activecpu].intf->cpu_state_save )
780 							(*cpu[activecpu].intf->cpu_state_save)(s);
781 					}
782 					state_close(s);
783 				}
784 			}
785 
786 			if( keyboard_pressed_memory(KEYCODE_L) )
787 			{
788 				void *s = state_open(Machine->gamedrv->name);
789 				if( s )
790 				{
791 					for( cpunum = 0; cpunum < totalcpu; cpunum++ )
792 					{
793 						activecpu = cpunum;
794 						memorycontextswap(activecpu);
795 						if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
796 						/* make sure any bank switching is reset */
797 						SET_OP_BASE(activecpu, GETPC(activecpu));
798 						if( cpu[activecpu].intf->cpu_state_load )
799 							(*cpu[activecpu].intf->cpu_state_load)(s);
800 						/* update the contexts */
801 						if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
802 					}
803 					state_close(s);
804 				}
805 			}
806 		}
807 #endif
808 		/* ask the timer system to schedule */
809 		if (timer_schedule_cpu(&cpunum, &cycles_running))
810 		{
811 			int ran;
812 
813 
814 			/* switch memory and CPU contexts */
815 			activecpu = cpunum;
816 			memorycontextswap(activecpu);
817 			if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
818 
819 			/* make sure any bank switching is reset */
820 			SET_OP_BASE(activecpu, GETPC(activecpu));
821 
822 			/* run for the requested number of cycles */
823 			profiler_mark(PROFILER_CPU1 + cpunum);
824 			ran = EXECUTE(activecpu, cycles_running);
825 			profiler_mark(PROFILER_END);
826 
827 			/* update based on how many cycles we really ran */
828 			cpu[activecpu].totalcycles += ran;
829 
830 			/* update the contexts */
831 			if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
832 			activecpu = -1;
833 
834 			/* update the timer with how long we actually ran */
835 			timer_update_cpu(cpunum, ran);
836 		}
837 
838 		profiler_mark(PROFILER_END);
839 	}
840 
841 	/* write hi scores to disk - No scores saving if cheat */
842 	hs_close();
843 
844 #ifdef MESS
845 	if (Machine->drv->stop_machine) (*Machine->drv->stop_machine)();
846 #endif
847 
848 	/* shut down the CPU cores */
849 	for (i = 0; i < totalcpu; i++)
850 	{
851 		/* if the CPU core defines an exit function, call it now */
852 		if( cpu[i].intf->exit )
853 			(*cpu[i].intf->exit)();
854 
855 		/* free the context buffer for that CPU */
856 		if( cpu[i].context )
857 		{
858 			free( cpu[i].context );
859 			cpu[i].context = NULL;
860 		}
861 	}
862 	totalcpu = 0;
863 #ifdef WANT_LIBCO
864                libco_quit=1;
865 #endif
866 }
867 
868 
869 
870 
871 /***************************************************************************
872 
873   Use this function to initialize, and later maintain, the watchdog. For
874   convenience, when the machine is reset, the watchdog is disabled. If you
875   call this function, the watchdog is initialized, and from that point
876   onwards, if you don't call it at least once every 2 seconds, the machine
877   will be reset.
878 
879   The 2 seconds delay is targeted at dondokod, which during boot stays more
880   than 1 second without resetting the watchdog.
881 
882 ***************************************************************************/
WRITE_HANDLER(watchdog_reset_w)883 WRITE_HANDLER( watchdog_reset_w )
884 {
885 	if (watchdog_counter == -1) logerror("watchdog armed\n");
886 	watchdog_counter = 2*Machine->drv->frames_per_second;
887 }
888 
READ_HANDLER(watchdog_reset_r)889 READ_HANDLER( watchdog_reset_r )
890 {
891 	if (watchdog_counter == -1) logerror("watchdog armed\n");
892 	watchdog_counter = 2*Machine->drv->frames_per_second;
893 	return 0;
894 }
895 
896 
897 
898 /***************************************************************************
899 
900   This function resets the machine (the reset will not take place
901   immediately, it will be performed at the end of the active CPU's time
902   slice)
903 
904 ***************************************************************************/
machine_reset(void)905 void machine_reset(void)
906 {
907 	/* write hi scores to disk - No scores saving if cheat */
908 	hs_close();
909 
910 	have_to_reset = 1;
911 }
912 
913 
914 
915 /***************************************************************************
916 
917   Use this function to reset a specified CPU immediately
918 
919 ***************************************************************************/
cpu_set_reset_line(int cpunum,int state)920 void cpu_set_reset_line(int cpunum,int state)
921 {
922 	timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_resetcallback);
923 }
924 
925 
926 /***************************************************************************
927 
928   Use this function to control the HALT line on a CPU
929 
930 ***************************************************************************/
cpu_set_halt_line(int cpunum,int state)931 void cpu_set_halt_line(int cpunum,int state)
932 {
933 	timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_haltcallback);
934 }
935 
936 
937 /***************************************************************************
938 
939   Use this function to install a callback for IRQ acknowledge
940 
941 ***************************************************************************/
cpu_set_irq_callback(int cpunum,int (* callback)(int))942 void cpu_set_irq_callback(int cpunum, int (*callback)(int))
943 {
944 	drv_irq_callbacks[cpunum] = callback;
945 }
946 
947 
948 /***************************************************************************
949 
950   This function returns CPUNUM current status  (running or halted)
951 
952 ***************************************************************************/
cpu_getstatus(int cpunum)953 int cpu_getstatus(int cpunum)
954 {
955 	if (cpunum >= MAX_CPU) return 0;
956 
957 	return !timer_iscpususpended(cpunum,
958 			SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE);
959 }
960 
961 
962 
cpu_getactivecpu(void)963 int cpu_getactivecpu(void)
964 {
965 	return (activecpu < 0) ? 0 : activecpu;
966 }
967 
cpu_setactivecpu(int cpunum)968 void cpu_setactivecpu(int cpunum)
969 {
970 	activecpu = cpunum;
971 }
972 
cpu_gettotalcpu(void)973 int cpu_gettotalcpu(void)
974 {
975 	return totalcpu;
976 }
977 
978 
979 
cpu_get_pc(void)980 unsigned cpu_get_pc(void)
981 {
982 	int cpunum = (activecpu < 0) ? 0 : activecpu;
983 	return GETPC(cpunum);
984 }
985 
cpu_set_pc(unsigned val)986 void cpu_set_pc(unsigned val)
987 {
988 	int cpunum = (activecpu < 0) ? 0 : activecpu;
989 	SETPC(cpunum,val);
990 }
991 
cpu_get_sp(void)992 unsigned cpu_get_sp(void)
993 {
994 	int cpunum = (activecpu < 0) ? 0 : activecpu;
995 	return GETSP(cpunum);
996 }
997 
cpu_set_sp(unsigned val)998 void cpu_set_sp(unsigned val)
999 {
1000 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1001 	SETSP(cpunum,val);
1002 }
1003 
1004 /* these are available externally, for the timer system */
cycles_currently_ran(void)1005 int cycles_currently_ran(void)
1006 {
1007 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1008 	return cycles_running - ICOUNT(cpunum);
1009 }
1010 
cycles_left_to_run(void)1011 int cycles_left_to_run(void)
1012 {
1013 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1014 	return ICOUNT(cpunum);
1015 }
1016 
1017 
1018 
1019 /***************************************************************************
1020 
1021   Returns the number of CPU cycles since the last reset of the CPU
1022 
1023   IMPORTANT: this value wraps around in a relatively short time.
1024   For example, for a 6Mhz CPU, it will wrap around in
1025   2^32/6000000 = 716 seconds = 12 minutes.
1026   Make sure you don't do comparisons between values returned by this
1027   function, but only use the difference (which will be correct regardless
1028   of wraparound).
1029 
1030 ***************************************************************************/
cpu_gettotalcycles(void)1031 int cpu_gettotalcycles(void)
1032 {
1033 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1034 	return cpu[cpunum].totalcycles + cycles_currently_ran();
1035 }
1036 
1037 
1038 
1039 /***************************************************************************
1040 
1041   Returns the number of CPU cycles before the next interrupt handler call
1042 
1043 ***************************************************************************/
cpu_geticount(void)1044 int cpu_geticount(void)
1045 {
1046 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1047 	int result = TIME_TO_CYCLES(cpunum, cpu[cpunum].vblankint_period - timer_timeelapsed(cpu[cpunum].vblankint_timer));
1048 	return (result < 0) ? 0 : result;
1049 }
1050 
1051 
1052 
1053 /***************************************************************************
1054 
1055   Returns the number of CPU cycles before the end of the current video frame
1056 
1057 ***************************************************************************/
cpu_getfcount(void)1058 int cpu_getfcount(void)
1059 {
1060 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1061 	int result = TIME_TO_CYCLES(cpunum, refresh_period - timer_timeelapsed(refresh_timer));
1062 	return (result < 0) ? 0 : result;
1063 }
1064 
1065 
1066 
1067 /***************************************************************************
1068 
1069   Returns the number of CPU cycles in one video frame
1070 
1071 ***************************************************************************/
cpu_getfperiod(void)1072 int cpu_getfperiod(void)
1073 {
1074 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1075 	return TIME_TO_CYCLES(cpunum, refresh_period);
1076 }
1077 
1078 
1079 
1080 /***************************************************************************
1081 
1082   Scales a given value by the ratio of fcount / fperiod
1083 
1084 ***************************************************************************/
cpu_scalebyfcount(int value)1085 int cpu_scalebyfcount(int value)
1086 {
1087     int result = ( ((INT64)value) * ((INT64)timer_timeelapsed(refresh_timer)) ) / ((INT64)refresh_period);
1088 	if (value >= 0) return (result < value) ? result : value;
1089 	else return (result > value) ? result : value;
1090 }
1091 
1092 
1093 
1094 /***************************************************************************
1095 
1096   Returns the current scanline, or the time until a specific scanline
1097 
1098   Note: cpu_getscanline() counts from 0, 0 being the first visible line. You
1099   might have to adjust this value to match the hardware, since in many cases
1100   the first visible line is >0.
1101 
1102 ***************************************************************************/
cpu_getscanline(void)1103 int cpu_getscanline(void)
1104 {
1105     return (int)(timer_timeelapsed(refresh_timer)/scanline_period);
1106 }
1107 
1108 
cpu_getscanlinetime(int scanline)1109 timer_tm cpu_getscanlinetime(int scanline)
1110 {
1111 	timer_tm ret;
1112     timer_tm scantime = ((timer_entry *)refresh_timer)->start + scanline*scanline_period;
1113     timer_tm abstime = getabsolutetime();
1114     if (abstime >= scantime) scantime += TIME_IN_HZ(Machine->drv->frames_per_second);
1115     ret = scantime - abstime;
1116     if (ret < 1)
1117     {
1118         ret = TIME_IN_HZ(Machine->drv->frames_per_second);
1119     }
1120 
1121 	return ret;
1122 }
1123 
1124 
cpu_getscanlineperiod(void)1125 timer_tm cpu_getscanlineperiod(void)
1126 {
1127 	return scanline_period;
1128 }
1129 
1130 
1131 /***************************************************************************
1132 
1133   Returns the number of cycles in a scanline
1134 
1135  ***************************************************************************/
cpu_getscanlinecycles(void)1136 int cpu_getscanlinecycles(void)
1137 {
1138 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1139 	return TIME_TO_CYCLES(cpunum, scanline_period);
1140 }
1141 
1142 
1143 /***************************************************************************
1144 
1145   Returns the number of cycles since the beginning of this frame
1146 
1147  ***************************************************************************/
cpu_getcurrentcycles(void)1148 int cpu_getcurrentcycles(void)
1149 {
1150 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1151 	return TIME_TO_CYCLES(cpunum, timer_timeelapsed(refresh_timer));
1152 }
1153 
1154 
1155 /***************************************************************************
1156 
1157   Returns the current horizontal beam position in pixels
1158 
1159  ***************************************************************************/
cpu_gethorzbeampos(void)1160 int cpu_gethorzbeampos(void)
1161 {
1162     /*
1163 	timer_tm elapsed_time = timer_timeelapsed(refresh_timer);
1164     int scanline = elapsed_time / scanline_period;
1165 	timer_tm time_since_scanline = elapsed_time - scanline * scanline_period;
1166 	*/
1167 	timer_tm time_since_scanline = timer_timeelapsed(refresh_timer) % scanline_period;
1168     return ( ((INT64)time_since_scanline) * ((INT64)Machine->drv->screen_width) ) / ((INT64)scanline_period);
1169 }
1170 
1171 
1172 /***************************************************************************
1173 
1174   Returns the number of times the interrupt handler will be called before
1175   the end of the current video frame. This can be useful to interrupt
1176   handlers to synchronize their operation. If you call this from outside
1177   an interrupt handler, add 1 to the result, i.e. if it returns 0, it means
1178   that the interrupt handler will be called once.
1179 
1180 ***************************************************************************/
cpu_getiloops(void)1181 int cpu_getiloops(void)
1182 {
1183 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1184 	return cpu[cpunum].iloops;
1185 }
1186 
1187 
1188 
1189 /***************************************************************************
1190 
1191   Interrupt handling
1192 
1193 ***************************************************************************/
1194 
1195 /***************************************************************************
1196 
1197   These functions are called when a cpu calls the callback sent to it's
1198   set_irq_callback function. It clears the irq line if the current state
1199   is HOLD_LINE and returns the interrupt vector for that line.
1200 
1201 ***************************************************************************/
1202 #define MAKE_IRQ_CALLBACK(num)												\
1203 static int cpu_##num##_irq_callback(int irqline)							\
1204 {																			\
1205 	int vector = irq_line_vector[num * MAX_IRQ_LINES + irqline];			\
1206     if( irq_line_state[num * MAX_IRQ_LINES + irqline] == HOLD_LINE )        \
1207 	{																		\
1208 		SETIRQLINE(num, irqline, CLEAR_LINE);								\
1209 		irq_line_state[num * MAX_IRQ_LINES + irqline] = CLEAR_LINE; 		\
1210 	}																		\
1211 	LOG(("cpu_##num##_irq_callback(%d) $%04x\n", irqline, vector));         \
1212 	if( drv_irq_callbacks[num] )											\
1213 		return (*drv_irq_callbacks[num])(vector);							\
1214 	return vector;															\
1215 }
1216 
1217 MAKE_IRQ_CALLBACK(0)
1218 MAKE_IRQ_CALLBACK(1)
1219 MAKE_IRQ_CALLBACK(2)
1220 MAKE_IRQ_CALLBACK(3)
1221 MAKE_IRQ_CALLBACK(4)
1222 MAKE_IRQ_CALLBACK(5)
1223 MAKE_IRQ_CALLBACK(6)
1224 MAKE_IRQ_CALLBACK(7)
1225 
1226 /***************************************************************************
1227 
1228   This function is used to generate internal interrupts (TMS34010)
1229 
1230 ***************************************************************************/
cpu_generate_internal_interrupt(int cpunum,int type)1231 void cpu_generate_internal_interrupt(int cpunum, int type)
1232 {
1233 	timer_set(TIME_NOW, (cpunum & 7) | (type << 3), cpu_internalintcallback);
1234 }
1235 
1236 
1237 /***************************************************************************
1238 
1239   Use this functions to set the vector for a irq line of a CPU
1240 
1241 ***************************************************************************/
cpu_irq_line_vector_w(int cpunum,int irqline,int vector)1242 void cpu_irq_line_vector_w(int cpunum, int irqline, int vector)
1243 {
1244 	cpunum &= (MAX_CPU - 1);
1245 	irqline &= (MAX_IRQ_LINES - 1);
1246 	if( irqline < cpu[cpunum].intf->num_irqs )
1247 	{
1248 		LOG(("cpu_irq_line_vector_w(%d,%d,$%04x)\n",cpunum,irqline,vector));
1249 		irq_line_vector[cpunum * MAX_IRQ_LINES + irqline] = vector;
1250 		return;
1251 	}
1252 	LOG(("cpu_irq_line_vector_w CPU#%d irqline %d > max irq lines\n", cpunum, irqline));
1253 }
1254 
1255 /***************************************************************************
1256 
1257   Use these functions to set the vector (data) for a irq line (offset)
1258   of CPU #0 to #3
1259 
1260 ***************************************************************************/
WRITE_HANDLER(cpu_0_irq_line_vector_w)1261 WRITE_HANDLER( cpu_0_irq_line_vector_w ) { cpu_irq_line_vector_w(0, offset, data); }
WRITE_HANDLER(cpu_1_irq_line_vector_w)1262 WRITE_HANDLER( cpu_1_irq_line_vector_w ) { cpu_irq_line_vector_w(1, offset, data); }
WRITE_HANDLER(cpu_2_irq_line_vector_w)1263 WRITE_HANDLER( cpu_2_irq_line_vector_w ) { cpu_irq_line_vector_w(2, offset, data); }
WRITE_HANDLER(cpu_3_irq_line_vector_w)1264 WRITE_HANDLER( cpu_3_irq_line_vector_w ) { cpu_irq_line_vector_w(3, offset, data); }
WRITE_HANDLER(cpu_4_irq_line_vector_w)1265 WRITE_HANDLER( cpu_4_irq_line_vector_w ) { cpu_irq_line_vector_w(4, offset, data); }
WRITE_HANDLER(cpu_5_irq_line_vector_w)1266 WRITE_HANDLER( cpu_5_irq_line_vector_w ) { cpu_irq_line_vector_w(5, offset, data); }
WRITE_HANDLER(cpu_6_irq_line_vector_w)1267 WRITE_HANDLER( cpu_6_irq_line_vector_w ) { cpu_irq_line_vector_w(6, offset, data); }
WRITE_HANDLER(cpu_7_irq_line_vector_w)1268 WRITE_HANDLER( cpu_7_irq_line_vector_w ) { cpu_irq_line_vector_w(7, offset, data); }
1269 
1270 /***************************************************************************
1271 
1272   Use this function to set the state the NMI line of a CPU
1273 
1274 ***************************************************************************/
cpu_set_nmi_line(int cpunum,int state)1275 void cpu_set_nmi_line(int cpunum, int state)
1276 {
1277 	/* don't trigger interrupts on suspended CPUs */
1278 	if (cpu_getstatus(cpunum) == 0) return;
1279 
1280 	LOG(("cpu_set_nmi_line(%d,%d)\n",cpunum,state));
1281 	timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_manualnmicallback);
1282 }
1283 
1284 /***************************************************************************
1285 
1286   Use this function to set the state of an IRQ line of a CPU
1287   The meaning of irqline varies between the different CPU types
1288 
1289 ***************************************************************************/
cpu_set_irq_line(int cpunum,int irqline,int state)1290 void cpu_set_irq_line(int cpunum, int irqline, int state)
1291 {
1292 	/* don't trigger interrupts on suspended CPUs */
1293 	if (cpu_getstatus(cpunum) == 0) return;
1294 
1295 	LOG(("cpu_set_irq_line(%d,%d,%d)\n",cpunum,irqline,state));
1296 	timer_set(TIME_NOW, (irqline & 7) | ((cpunum & 7) << 3) | (state << 6), cpu_manualirqcallback);
1297 }
1298 
1299 /***************************************************************************
1300 
1301   Use this function to cause an interrupt immediately (don't have to wait
1302   until the next call to the interrupt handler)
1303 
1304 ***************************************************************************/
cpu_cause_interrupt(int cpunum,int type)1305 void cpu_cause_interrupt(int cpunum,int type)
1306 {
1307 	/* don't trigger interrupts on suspended CPUs */
1308 	if (cpu_getstatus(cpunum) == 0) return;
1309 
1310 	timer_set(TIME_NOW, (cpunum & 7) | (type << 3), cpu_manualintcallback);
1311 }
1312 
1313 
1314 
cpu_clear_pending_interrupts(int cpunum)1315 void cpu_clear_pending_interrupts(int cpunum)
1316 {
1317 	timer_set(TIME_NOW, cpunum, cpu_clearintcallback);
1318 }
1319 
1320 
1321 
WRITE_HANDLER(interrupt_enable_w)1322 WRITE_HANDLER( interrupt_enable_w )
1323 {
1324 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1325 	interrupt_enable[cpunum] = data;
1326 
1327 	/* make sure there are no queued interrupts */
1328 	if (data == 0) cpu_clear_pending_interrupts(cpunum);
1329 }
1330 
1331 
1332 
WRITE_HANDLER(interrupt_vector_w)1333 WRITE_HANDLER( interrupt_vector_w )
1334 {
1335 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1336 	if (interrupt_vector[cpunum] != data)
1337 	{
1338 		LOG(("CPU#%d interrupt_vector_w $%02x\n", cpunum, data));
1339 		interrupt_vector[cpunum] = data;
1340 
1341 		/* make sure there are no queued interrupts */
1342 		cpu_clear_pending_interrupts(cpunum);
1343 	}
1344 }
1345 
1346 
1347 
interrupt(void)1348 int interrupt(void)
1349 {
1350 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1351 	int val;
1352 
1353 	if (interrupt_enable[cpunum] == 0)
1354 		return INT_TYPE_NONE(cpunum);
1355 
1356 	val = INT_TYPE_IRQ(cpunum);
1357 	if (val == -1000)
1358 		val = interrupt_vector[cpunum];
1359 
1360 	return val;
1361 }
1362 
1363 
1364 
nmi_interrupt(void)1365 int nmi_interrupt(void)
1366 {
1367 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1368 
1369 	if (interrupt_enable[cpunum] == 0)
1370 		return INT_TYPE_NONE(cpunum);
1371 
1372 	return INT_TYPE_NMI(cpunum);
1373 }
1374 
1375 
1376 
m68_level1_irq(void)1377 int m68_level1_irq(void)
1378 {
1379 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1380 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1381 	return MC68000_IRQ_1;
1382 }
m68_level2_irq(void)1383 int m68_level2_irq(void)
1384 {
1385 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1386 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1387 	return MC68000_IRQ_2;
1388 }
m68_level3_irq(void)1389 int m68_level3_irq(void)
1390 {
1391 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1392 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1393 	return MC68000_IRQ_3;
1394 }
m68_level4_irq(void)1395 int m68_level4_irq(void)
1396 {
1397 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1398 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1399 	return MC68000_IRQ_4;
1400 }
m68_level5_irq(void)1401 int m68_level5_irq(void)
1402 {
1403 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1404 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1405 	return MC68000_IRQ_5;
1406 }
m68_level6_irq(void)1407 int m68_level6_irq(void)
1408 {
1409 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1410 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1411 	return MC68000_IRQ_6;
1412 }
m68_level7_irq(void)1413 int m68_level7_irq(void)
1414 {
1415 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1416 	if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1417 	return MC68000_IRQ_7;
1418 }
1419 
1420 
1421 
ignore_interrupt(void)1422 int ignore_interrupt(void)
1423 {
1424 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1425 	return INT_TYPE_NONE(cpunum);
1426 }
1427 
1428 
1429 
1430 /***************************************************************************
1431 
1432   CPU timing and synchronization functions.
1433 
1434 ***************************************************************************/
1435 
1436 /* generate a trigger */
cpu_trigger(int trigger)1437 void cpu_trigger(int trigger)
1438 {
1439 	timer_trigger(trigger);
1440 }
1441 
1442 /* generate a trigger after a specific period of time */
cpu_triggertime(timer_tm duration,int trigger)1443 void cpu_triggertime(timer_tm duration, int trigger)
1444 {
1445 	timer_set(duration, trigger, cpu_trigger);
1446 }
1447 
1448 
1449 
1450 /* burn CPU cycles until a timer trigger */
cpu_spinuntil_trigger(int trigger)1451 void cpu_spinuntil_trigger(int trigger)
1452 {
1453 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1454 	timer_suspendcpu_trigger(cpunum, trigger);
1455 }
1456 
1457 /* burn CPU cycles until the next interrupt */
cpu_spinuntil_int(void)1458 void cpu_spinuntil_int(void)
1459 {
1460 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1461 	cpu_spinuntil_trigger(TRIGGER_INT + cpunum);
1462 }
1463 
1464 /* burn CPU cycles until our timeslice is up */
cpu_spin(void)1465 void cpu_spin(void)
1466 {
1467 	cpu_spinuntil_trigger(TRIGGER_TIMESLICE);
1468 }
1469 
1470 /* burn CPU cycles for a specific period of time */
cpu_spinuntil_time(timer_tm duration)1471 void cpu_spinuntil_time(timer_tm duration)
1472 {
1473 	static int timetrig = 0;
1474 
1475 	cpu_spinuntil_trigger(TRIGGER_SUSPENDTIME + timetrig);
1476 	cpu_triggertime(duration, TRIGGER_SUSPENDTIME + timetrig);
1477 	timetrig = (timetrig + 1) & 255;
1478 }
1479 
1480 
1481 
1482 /* yield our timeslice for a specific period of time */
cpu_yielduntil_trigger(int trigger)1483 void cpu_yielduntil_trigger(int trigger)
1484 {
1485 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1486 	timer_holdcpu_trigger(cpunum, trigger);
1487 }
1488 
1489 /* yield our timeslice until the next interrupt */
cpu_yielduntil_int(void)1490 void cpu_yielduntil_int(void)
1491 {
1492 	int cpunum = (activecpu < 0) ? 0 : activecpu;
1493 	cpu_yielduntil_trigger(TRIGGER_INT + cpunum);
1494 }
1495 
1496 /* yield our current timeslice */
cpu_yield(void)1497 void cpu_yield(void)
1498 {
1499 	cpu_yielduntil_trigger(TRIGGER_TIMESLICE);
1500 }
1501 
1502 /* yield our timeslice for a specific period of time */
cpu_yielduntil_time(timer_tm duration)1503 void cpu_yielduntil_time(timer_tm duration)
1504 {
1505 	static int timetrig = 0;
1506 
1507 	cpu_yielduntil_trigger(TRIGGER_YIELDTIME + timetrig);
1508 	cpu_triggertime(duration, TRIGGER_YIELDTIME + timetrig);
1509 	timetrig = (timetrig + 1) & 255;
1510 }
1511 
1512 
1513 
cpu_getvblank(void)1514 int cpu_getvblank(void)
1515 {
1516 	return vblank;
1517 }
1518 
1519 
cpu_getcurrentframe(void)1520 int cpu_getcurrentframe(void)
1521 {
1522 	return current_frame;
1523 }
1524 
1525 
1526 /***************************************************************************
1527 
1528   Internal CPU event processors.
1529 
1530 ***************************************************************************/
1531 
cpu_manualnmicallback(int param)1532 static void cpu_manualnmicallback(int param)
1533 {
1534 	int cpunum, state, oldactive;
1535 	cpunum = param & 7;
1536 	state = param >> 3;
1537 
1538 	/* swap to the CPU's context */
1539 	oldactive = activecpu;
1540 	activecpu = cpunum;
1541 	memorycontextswap(activecpu);
1542 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1543 
1544 	LOG(("cpu_manualnmicallback %d,%d\n",cpunum,state));
1545 
1546 	switch (state)
1547 	{
1548 		case PULSE_LINE:
1549 			SETNMILINE(cpunum,ASSERT_LINE);
1550 			SETNMILINE(cpunum,CLEAR_LINE);
1551 			break;
1552 		case HOLD_LINE:
1553 		case ASSERT_LINE:
1554 			SETNMILINE(cpunum,ASSERT_LINE);
1555 			break;
1556 		case CLEAR_LINE:
1557 			SETNMILINE(cpunum,CLEAR_LINE);
1558 			break;
1559 		default:
1560 			logerror("cpu_manualnmicallback cpu #%d unknown state %d\n", cpunum, state);
1561 	}
1562 	/* update the CPU's context */
1563 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1564 	activecpu = oldactive;
1565 	if (activecpu >= 0) memorycontextswap(activecpu);
1566 
1567 	/* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1568 	if (state != CLEAR_LINE)
1569 		timer_trigger(TRIGGER_INT + cpunum);
1570 }
1571 
cpu_manualirqcallback(int param)1572 static void cpu_manualirqcallback(int param)
1573 {
1574 	int cpunum, irqline, state, oldactive;
1575 
1576 	irqline = param & 7;
1577 	cpunum = (param >> 3) & 7;
1578 	state = param >> 6;
1579 
1580 	/* swap to the CPU's context */
1581 	oldactive = activecpu;
1582 	activecpu = cpunum;
1583 	memorycontextswap(activecpu);
1584 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1585 
1586 	LOG(("cpu_manualirqcallback %d,%d,%d\n",cpunum,irqline,state));
1587 
1588 	irq_line_state[cpunum * MAX_IRQ_LINES + irqline] = state;
1589 	switch (state)
1590 	{
1591 		case PULSE_LINE:
1592 			SETIRQLINE(cpunum,irqline,ASSERT_LINE);
1593 			SETIRQLINE(cpunum,irqline,CLEAR_LINE);
1594 			break;
1595 		case HOLD_LINE:
1596 		case ASSERT_LINE:
1597 			SETIRQLINE(cpunum,irqline,ASSERT_LINE);
1598 			break;
1599 		case CLEAR_LINE:
1600 			SETIRQLINE(cpunum,irqline,CLEAR_LINE);
1601 			break;
1602 		default:
1603 			logerror("cpu_manualirqcallback cpu #%d, line %d, unknown state %d\n", cpunum, irqline, state);
1604 	}
1605 
1606 	/* update the CPU's context */
1607 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1608 	activecpu = oldactive;
1609 	if (activecpu >= 0) memorycontextswap(activecpu);
1610 
1611 	/* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1612 	if (state != CLEAR_LINE)
1613 		timer_trigger(TRIGGER_INT + cpunum);
1614 }
1615 
cpu_internal_interrupt(int cpunum,int type)1616 static void cpu_internal_interrupt(int cpunum, int type)
1617 {
1618 	int oldactive = activecpu;
1619 
1620 	/* swap to the CPU's context */
1621 	activecpu = cpunum;
1622 	memorycontextswap(activecpu);
1623 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1624 
1625 	INTERNAL_INTERRUPT(cpunum, type);
1626 
1627 	/* update the CPU's context */
1628 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1629 	activecpu = oldactive;
1630 	if (activecpu >= 0) memorycontextswap(activecpu);
1631 
1632 	/* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1633 	timer_trigger(TRIGGER_INT + cpunum);
1634 }
1635 
cpu_internalintcallback(int param)1636 static void cpu_internalintcallback(int param)
1637 {
1638 	int type = param >> 3;
1639 	int cpunum = param & 7;
1640 
1641 	LOG(("CPU#%d internal interrupt type $%04x\n", cpunum, type));
1642 	/* generate the interrupt */
1643 	cpu_internal_interrupt(cpunum, type);
1644 }
1645 
cpu_generate_interrupt(int cpunum,int (* func)(void),int num)1646 static void cpu_generate_interrupt(int cpunum, int (*func)(void), int num)
1647 {
1648 	int oldactive = activecpu;
1649 
1650 	/* don't trigger interrupts on suspended CPUs */
1651 	if (cpu_getstatus(cpunum) == 0) return;
1652 
1653 	/* swap to the CPU's context */
1654 	activecpu = cpunum;
1655 	memorycontextswap(activecpu);
1656 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1657 
1658 	/* cause the interrupt, calling the function if it exists */
1659 	if (func) num = (*func)();
1660 
1661 	/* wrapper for the new interrupt system */
1662 	if (num != INT_TYPE_NONE(cpunum))
1663 	{
1664 		LOG(("CPU#%d interrupt type $%04x: ", cpunum, num));
1665 		/* is it the NMI type interrupt of that CPU? */
1666 		if (num == INT_TYPE_NMI(cpunum))
1667 		{
1668 
1669 			LOG(("NMI\n"));
1670 			cpu_manualnmicallback(cpunum | (PULSE_LINE << 3) );
1671 
1672 		}
1673 		else
1674 		{
1675 			int irq_line=0;
1676 
1677 			switch (CPU_TYPE(cpunum))
1678 			{
1679 #if (HAS_8085A)
1680 			case CPU_8085A:
1681 				switch (num)
1682 				{
1683 				case I8085_RST55:		irq_line = 1; break;
1684 				case I8085_RST65:		irq_line = 2; break;
1685 				case I8085_RST75:		irq_line = 3; break;
1686 				}
1687 				break;
1688 #endif
1689 #if (HAS_H6280)
1690 			case CPU_H6280:
1691 				switch (num)
1692 				{
1693 				case H6280_INT_IRQ2:	irq_line = 1; break;
1694 				case H6280_INT_TIMER:	irq_line = 2; break;
1695 				}
1696 				break;
1697 #endif
1698 #if (HAS_HD6309)
1699 			case CPU_HD6309:
1700 			    if (num==HD6309_INT_FIRQ) irq_line = 1;
1701 			    break;
1702 #endif
1703 #if (HAS_M6809)
1704 			case CPU_M6809:
1705 			    if (num==M6809_INT_FIRQ) irq_line = 1;
1706 				break;
1707 #endif
1708 #if (HAS_KONAMI)
1709 				case CPU_KONAMI:
1710 				if (num==KONAMI_INT_FIRQ) irq_line = 1;
1711 				break;
1712 #endif
1713 #if (HAS_M68000)
1714 			case CPU_M68000:
1715 				switch (num)
1716 				{
1717 				case MC68000_IRQ_1: 	irq_line = 1; break;
1718 				case MC68000_IRQ_2: 	irq_line = 2; break;
1719 				case MC68000_IRQ_3: 	irq_line = 3; break;
1720 				case MC68000_IRQ_4: 	irq_line = 4; break;
1721 				case MC68000_IRQ_5: 	irq_line = 5; break;
1722 				case MC68000_IRQ_6: 	irq_line = 6; break;
1723 				case MC68000_IRQ_7: 	irq_line = 7; break;
1724 				}
1725 				/* until now only auto vector interrupts supported */
1726 				num = MC68000_INT_ACK_AUTOVECTOR;
1727 				break;
1728 #endif
1729 #if (HAS_CYCLONE)
1730 			case CPU_CYCLONE:
1731 				switch (num)
1732 				{
1733 				case cyclone_IRQ_1: 	irq_line = 1; break;
1734 				case cyclone_IRQ_2: 	irq_line = 2; break;
1735 				case cyclone_IRQ_3: 	irq_line = 3; break;
1736 				case cyclone_IRQ_4: 	irq_line = 4; break;
1737 				case cyclone_IRQ_5: 	irq_line = 5; break;
1738 				case cyclone_IRQ_6: 	irq_line = 6; break;
1739 				case cyclone_IRQ_7: 	irq_line = 7; break;
1740 				}
1741 				/* until now only auto vector interrupts supported */
1742 				num = cyclone_INT_ACK_AUTOVECTOR;
1743 				break;
1744 #endif
1745 #if (HAS_M68010)
1746 			case CPU_M68010:
1747 				switch (num)
1748 				{
1749 				case MC68010_IRQ_1: 	irq_line = 1; break;
1750 				case MC68010_IRQ_2: 	irq_line = 2; break;
1751 				case MC68010_IRQ_3: 	irq_line = 3; break;
1752 				case MC68010_IRQ_4: 	irq_line = 4; break;
1753 				case MC68010_IRQ_5: 	irq_line = 5; break;
1754 				case MC68010_IRQ_6: 	irq_line = 6; break;
1755 				case MC68010_IRQ_7: 	irq_line = 7; break;
1756 				}
1757 				/* until now only auto vector interrupts supported */
1758 				num = MC68000_INT_ACK_AUTOVECTOR;
1759 				break;
1760 #endif
1761 #if (HAS_M68020)
1762 			case CPU_M68020:
1763 				switch (num)
1764 				{
1765 				case MC68020_IRQ_1: 	irq_line = 1; break;
1766 				case MC68020_IRQ_2: 	irq_line = 2; break;
1767 				case MC68020_IRQ_3: 	irq_line = 3; break;
1768 				case MC68020_IRQ_4: 	irq_line = 4; break;
1769 				case MC68020_IRQ_5: 	irq_line = 5; break;
1770 				case MC68020_IRQ_6: 	irq_line = 6; break;
1771 				case MC68020_IRQ_7: 	irq_line = 7; break;
1772 				}
1773 				/* until now only auto vector interrupts supported */
1774 				num = MC68000_INT_ACK_AUTOVECTOR;
1775 				break;
1776 #endif
1777 #if (HAS_M68EC020)
1778 			case CPU_M68EC020:
1779 				switch (num)
1780 				{
1781 				case MC68EC020_IRQ_1:	irq_line = 1; break;
1782 				case MC68EC020_IRQ_2:	irq_line = 2; break;
1783 				case MC68EC020_IRQ_3:	irq_line = 3; break;
1784 				case MC68EC020_IRQ_4:	irq_line = 4; break;
1785 				case MC68EC020_IRQ_5:	irq_line = 5; break;
1786 				case MC68EC020_IRQ_6:	irq_line = 6; break;
1787 				case MC68EC020_IRQ_7:	irq_line = 7; break;
1788 				}
1789 				/* until now only auto vector interrupts supported */
1790 				num = MC68000_INT_ACK_AUTOVECTOR;
1791 				break;
1792 #endif
1793 #if (HAS_T11)
1794 			case CPU_T11:
1795 				switch (num)
1796 				{
1797 				case T11_IRQ0:			irq_line = 0; break;
1798 				case T11_IRQ1:			irq_line = 1; break;
1799 				case T11_IRQ2:			irq_line = 2; break;
1800 				case T11_IRQ3:			irq_line = 3; break;
1801 				}
1802 				break;
1803 #endif
1804 #if (HAS_TMS34010)
1805 			case CPU_TMS34010:
1806 			    if (num==TMS34010_INT2) irq_line = 1;
1807 				break;
1808 #endif
1809 #if (HAS_Z8000)
1810                 if (num==Z8000_VI) irq_line = 1;
1811 				break;
1812 #endif
1813 #if (HAS_TMS320C10)
1814 			case CPU_TMS320C10:
1815 			    if (num==TMS320C10_ACTIVE_BIO) irq_line = 1;
1816 				break;
1817 #endif
1818 #if (HAS_ADSP2100)
1819 			case CPU_ADSP2100:
1820 				switch (num)
1821 				{
1822 				case ADSP2100_IRQ1: 		irq_line = 1; break;
1823 				case ADSP2100_IRQ2: 		irq_line = 2; break;
1824 				case ADSP2100_IRQ3: 		irq_line = 3; break;
1825 				}
1826 				break;
1827 #endif
1828 			}
1829 			LOG(("IRQ %d\n",irq_line));
1830 			cpu_irq_line_vector_w(cpunum, irq_line, num);
1831 			cpu_manualirqcallback(irq_line | (cpunum << 3) | (HOLD_LINE << 6) );
1832 		}
1833 	}
1834 
1835 	/* update the CPU's context */
1836 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1837 	activecpu = oldactive;
1838 	if (activecpu >= 0) memorycontextswap(activecpu);
1839 
1840 	/* trigger already generated by cpu_manualirqcallback or cpu_manualnmicallback */
1841 }
1842 
cpu_clear_interrupts(int cpunum)1843 static void cpu_clear_interrupts(int cpunum)
1844 {
1845 	int oldactive = activecpu;
1846 	int i;
1847 
1848 	/* swap to the CPU's context */
1849 	activecpu = cpunum;
1850 	memorycontextswap(activecpu);
1851 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1852 
1853 	/* clear NMI line */
1854 	SETNMILINE(activecpu,CLEAR_LINE);
1855 
1856 	/* clear all IRQ lines */
1857 	for (i = 0; i < cpu[activecpu].intf->num_irqs; i++)
1858 		SETIRQLINE(activecpu,i,CLEAR_LINE);
1859 
1860 	/* update the CPU's context */
1861 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1862 	activecpu = oldactive;
1863 	if (activecpu >= 0) memorycontextswap(activecpu);
1864 }
1865 
1866 
cpu_reset_cpu(int cpunum)1867 static void cpu_reset_cpu(int cpunum)
1868 {
1869 	int oldactive = activecpu;
1870 
1871 	/* swap to the CPU's context */
1872 	activecpu = cpunum;
1873 	memorycontextswap(activecpu);
1874 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1875 
1876 	/* reset the CPU */
1877 	RESET(cpunum);
1878 
1879 	/* Set the irq callback for the cpu */
1880 	SETIRQCALLBACK(cpunum,cpu_irq_callbacks[cpunum]);
1881 
1882 	/* update the CPU's context */
1883 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1884 	activecpu = oldactive;
1885 	if (activecpu >= 0) memorycontextswap(activecpu);
1886 }
1887 
1888 /***************************************************************************
1889 
1890   Interrupt callback. This is called once per CPU interrupt by either the
1891   VBLANK handler or by the CPU's own timer directly, depending on whether
1892   or not the CPU's interrupts are synced to VBLANK.
1893 
1894 ***************************************************************************/
cpu_vblankintcallback(int param)1895 static void cpu_vblankintcallback(int param)
1896 {
1897 	if (Machine->drv->cpu[param].vblank_interrupt)
1898 		cpu_generate_interrupt(param, Machine->drv->cpu[param].vblank_interrupt, 0);
1899 
1900 	/* update the counters */
1901 	cpu[param].iloops--;
1902 }
1903 
1904 
cpu_timedintcallback(int param)1905 static void cpu_timedintcallback(int param)
1906 {
1907 	/* bail if there is no routine */
1908 	if (!Machine->drv->cpu[param].timed_interrupt)
1909 		return;
1910 
1911 	/* generate the interrupt */
1912 	cpu_generate_interrupt(param, Machine->drv->cpu[param].timed_interrupt, 0);
1913 }
1914 
1915 
cpu_manualintcallback(int param)1916 static void cpu_manualintcallback(int param)
1917 {
1918 	int intnum = param >> 3;
1919 	int cpunum = param & 7;
1920 
1921 	/* generate the interrupt */
1922 	cpu_generate_interrupt(cpunum, 0, intnum);
1923 }
1924 
1925 
cpu_clearintcallback(int param)1926 static void cpu_clearintcallback(int param)
1927 {
1928 	/* clear the interrupts */
1929 	cpu_clear_interrupts(param);
1930 }
1931 
1932 
cpu_resetcallback(int param)1933 static void cpu_resetcallback(int param)
1934 {
1935 	int state = param >> 3;
1936 	int cpunum = param & 7;
1937 
1938 	/* reset the CPU */
1939 	if (state == PULSE_LINE)
1940 		cpu_reset_cpu(cpunum);
1941 	else if (state == ASSERT_LINE)
1942 	{
1943 /* ASG - do we need this?		cpu_reset_cpu(cpunum);*/
1944 		timer_suspendcpu(cpunum, 1, SUSPEND_REASON_RESET);	/* halt cpu */
1945 	}
1946 	else if (state == CLEAR_LINE)
1947 	{
1948 		if (timer_iscpususpended(cpunum, SUSPEND_REASON_RESET))
1949 			cpu_reset_cpu(cpunum);
1950 		timer_suspendcpu(cpunum, 0, SUSPEND_REASON_RESET);	/* restart cpu */
1951 	}
1952 }
1953 
1954 
cpu_haltcallback(int param)1955 static void cpu_haltcallback(int param)
1956 {
1957 	int state = param >> 3;
1958 	int cpunum = param & 7;
1959 
1960 	/* reset the CPU */
1961 	if (state == ASSERT_LINE)
1962 		timer_suspendcpu(cpunum, 1, SUSPEND_REASON_HALT);	/* halt cpu */
1963 	else if (state == CLEAR_LINE)
1964 		timer_suspendcpu(cpunum, 0, SUSPEND_REASON_HALT);	/* restart cpu */
1965 }
1966 
1967 
1968 
1969 /***************************************************************************
1970 
1971   VBLANK reset. Called at the start of emulation and once per VBLANK in
1972   order to update the input ports and reset the interrupt counter.
1973 
1974 ***************************************************************************/
cpu_vblankreset(void)1975 static void cpu_vblankreset(void)
1976 {
1977 	int i;
1978 
1979 	/* read hi scores from disk */
1980 	hs_update();
1981 
1982 	/* read keyboard & update the status of the input ports */
1983 	update_input_ports();
1984 
1985 	/* reset the cycle counters */
1986 	for (i = 0; i < totalcpu; i++)
1987 	{
1988 		if (!timer_iscpususpended(i, SUSPEND_ANY_REASON))
1989 			cpu[i].iloops = Machine->drv->cpu[i].vblank_interrupts_per_frame - 1;
1990 		else
1991 			cpu[i].iloops = -1;
1992 	}
1993 }
1994 
1995 
1996 /***************************************************************************
1997 
1998   VBLANK callback. This is called 'vblank_multipler' times per frame to
1999   service VBLANK-synced interrupts and to begin the screen update process.
2000 
2001 ***************************************************************************/
cpu_firstvblankcallback(int param)2002 static void cpu_firstvblankcallback(int param)
2003 {
2004 	/* now that we're synced up, pulse from here on out */
2005 	vblank_timer = timer_pulse(vblank_period, param, cpu_vblankcallback);
2006 
2007 	/* but we need to call the standard routine as well */
2008 	cpu_vblankcallback(param);
2009 }
2010 
2011 /* note that calling this with param == -1 means count everything, but call no subroutines */
cpu_vblankcallback(int param)2012 static void cpu_vblankcallback(int param)
2013 {
2014 	int i;
2015 
2016 	/* loop over CPUs */
2017 	for (i = 0; i < totalcpu; i++)
2018 	{
2019 		/* if the interrupt multiplier is valid */
2020 		if (cpu[i].vblankint_multiplier != -1)
2021 		{
2022 			/* decrement; if we hit zero, generate the interrupt and reset the countdown */
2023 			if (!--cpu[i].vblankint_countdown)
2024 			{
2025 				if (param != -1)
2026 					cpu_vblankintcallback(i);
2027 				cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier;
2028 				timer_reset(cpu[i].vblankint_timer, TIME_NEVER);
2029 			}
2030 		}
2031 
2032 		/* else reset the VBLANK timer if this is going to be a real VBLANK */
2033 		else if (vblank_countdown == 1)
2034 			timer_reset(cpu[i].vblankint_timer, TIME_NEVER);
2035 	}
2036 
2037 	/* is it a real VBLANK? */
2038 	if (!--vblank_countdown)
2039 	{
2040 		/* do we update the screen now? */
2041 		if (!(Machine->drv->video_attributes & VIDEO_UPDATE_AFTER_VBLANK))
2042 			usres = updatescreen();
2043 
2044 		/* Set the timer to update the screen */
2045 		timer_set(TIME_IN_USEC(Machine->drv->vblank_duration), 0, cpu_updatecallback);
2046 		vblank = 1;
2047 
2048 		/* reset the globals */
2049 		cpu_vblankreset();
2050 
2051 		/* reset the counter */
2052 		vblank_countdown = vblank_multiplier;
2053 	}
2054 }
2055 
2056 
2057 /***************************************************************************
2058 
2059   Video update callback. This is called a game-dependent amount of time
2060   after the VBLANK in order to trigger a video update.
2061 
2062 ***************************************************************************/
cpu_updatecallback(int param)2063 static void cpu_updatecallback(int param)
2064 {
2065 	/* update the screen if we didn't before */
2066 	if (Machine->drv->video_attributes & VIDEO_UPDATE_AFTER_VBLANK)
2067 		usres = updatescreen();
2068 	vblank = 0;
2069 
2070 	/* update IPT_VBLANK input ports */
2071 	inputport_vblank_end();
2072 
2073 	/* check the watchdog */
2074 	if (watchdog_counter > 0)
2075 	{
2076 		if (--watchdog_counter == 0)
2077 		{
2078 logerror("reset caused by the watchdog\n");
2079 			machine_reset();
2080 		}
2081 	}
2082 
2083 	current_frame++;
2084 
2085 	/* reset the refresh timer */
2086 	timer_reset(refresh_timer, TIME_NEVER);
2087 }
2088 
2089 
2090 /***************************************************************************
2091 
2092   Converts an integral timing rate into a period. Rates can be specified
2093   as follows:
2094 
2095 		rate > 0	   -> 'rate' cycles per frame
2096 		rate == 0	   -> 0
2097 		rate >= -10000 -> 'rate' cycles per second
2098 		rate < -10000  -> 'rate' nanoseconds
2099 
2100 ***************************************************************************/
cpu_computerate(int value)2101 static timer_tm cpu_computerate(int value)
2102 {
2103 	/* values equal to zero are zero */
2104 	if (value <= 0)
2105 		return 0;
2106 
2107 	/* values above between 0 and 50000 are in Hz */
2108 	if (value < 50000)
2109 		return TIME_IN_HZ(value);
2110 
2111 	/* values greater than 50000 are in nanoseconds */
2112 	else
2113 		return TIME_IN_NSEC(value);
2114 }
2115 
2116 
cpu_timeslicecallback(int param)2117 static void cpu_timeslicecallback(int param)
2118 {
2119 	timer_trigger(TRIGGER_TIMESLICE);
2120 }
2121 
2122 
2123 /***************************************************************************
2124 
2125   Initializes all the timers used by the CPU system.
2126 
2127 ***************************************************************************/
cpu_inittimers(void)2128 static void cpu_inittimers(void)
2129 {
2130 	timer_tm first_time;
2131 	int i, max, ipf;
2132 
2133 /*
2134 #ifdef MAME_FASTSOUND
2135 {
2136     extern int fast_sound;
2137     if (fast_sound)
2138     {
2139         // M72 sound hack
2140         if ((strcmp(Machine->gamedrv->name,"bchopper")==0) || (strcmp(Machine->gamedrv->name,"mrheli")==0) || (strcmp(Machine->gamedrv->name,"nspirit")==0) ||
2141             (strcmp(Machine->gamedrv->name,"nspiritj")==0) || (strcmp(Machine->gamedrv->name,"imgfight")==0) || (strcmp(Machine->gamedrv->name,"loht")==0) ||
2142             (strcmp(Machine->gamedrv->name,"xmultipl")==0) || (strcmp(Machine->gamedrv->name,"dbreed")==0) || (strcmp(Machine->gamedrv->name,"rtype2")==0) ||
2143             (strcmp(Machine->gamedrv->name,"rtype2j")==0) || (strcmp(Machine->gamedrv->name,"majtitle")==0) || (strcmp(Machine->gamedrv->name,"hharry")==0) ||
2144             (strcmp(Machine->gamedrv->name,"hharryu")==0) || (strcmp(Machine->gamedrv->name,"dkgensan")==0) || (strcmp(Machine->gamedrv->name,"kengo")==0) ||
2145             (strcmp(Machine->gamedrv->name,"poundfor")==0) || (strcmp(Machine->gamedrv->name,"poundfou")==0) || (strcmp(Machine->gamedrv->name,"airduel")==0) ||
2146             (strcmp(Machine->gamedrv->name,"gallop")==0))
2147         {
2148             int *ptr=(int *)&Machine->drv->cpu[1].vblank_interrupts_per_frame;
2149             *ptr=1;
2150         }
2151     }
2152 }
2153 #endif
2154 */
2155 
2156 	/* remove old timers */
2157 	if (timeslice_timer)
2158 		timer_remove(timeslice_timer);
2159 	if (refresh_timer)
2160 		timer_remove(refresh_timer);
2161 	if (vblank_timer)
2162 		timer_remove(vblank_timer);
2163 
2164 	/* allocate a dummy timer at the minimum frequency to break things up */
2165 	ipf = Machine->drv->cpu_slices_per_frame;
2166 	if (ipf <= 0)
2167 		ipf = 1;
2168 	timeslice_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf);
2169 	timeslice_timer = timer_pulse(timeslice_period, 0, cpu_timeslicecallback);
2170 
2171 	/* allocate an infinite timer to track elapsed time since the last refresh */
2172 	refresh_period = TIME_IN_HZ(Machine->drv->frames_per_second);
2173 	refresh_timer = timer_set(TIME_NEVER, 0, NULL);
2174 
2175 	/* while we're at it, compute the scanline times */
2176 	if (Machine->drv->vblank_duration)
2177 		scanline_period = (refresh_period - TIME_IN_USEC(Machine->drv->vblank_duration)) /
2178 				(timer_tm)(Machine->visible_area.max_y - Machine->visible_area.min_y + 1);
2179 	else
2180 		scanline_period = refresh_period / (timer_tm)Machine->drv->screen_height;
2181 
2182 	/*
2183 	 *		The following code finds all the CPUs that are interrupting in sync with the VBLANK
2184 	 *		and sets up the VBLANK timer to run at the minimum number of cycles per frame in
2185 	 *		order to service all the synced interrupts
2186 	 */
2187 
2188 	/* find the CPU with the maximum interrupts per frame */
2189 	max = 1;
2190 	for (i = 0; i < totalcpu; i++)
2191 	{
2192 		ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2193 		if (ipf > max)
2194 			max = ipf;
2195 	}
2196 
2197 	/* now find the LCD with the rest of the CPUs (brute force - these numbers aren't huge) */
2198 	vblank_multiplier = max;
2199 	while (1)
2200 	{
2201 		for (i = 0; i < totalcpu; i++)
2202 		{
2203 			ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2204 			if (ipf > 0 && (vblank_multiplier % ipf) != 0)
2205 				break;
2206 		}
2207 		if (i == totalcpu)
2208 			break;
2209 		vblank_multiplier += max;
2210 	}
2211 
2212 	/* initialize the countdown timers and intervals */
2213 	for (i = 0; i < totalcpu; i++)
2214 	{
2215 		ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2216 		if (ipf > 0)
2217 			cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier = vblank_multiplier / ipf;
2218 		else
2219 			cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier = -1;
2220 	}
2221 
2222 	/* allocate a vblank timer at the frame rate * the LCD number of interrupts per frame */
2223 	vblank_period = TIME_IN_HZ(Machine->drv->frames_per_second * vblank_multiplier);
2224 	vblank_timer = timer_pulse(vblank_period, 0, cpu_vblankcallback);
2225 	vblank_countdown = vblank_multiplier;
2226 
2227 	/*
2228 	 *		The following code creates individual timers for each CPU whose interrupts are not
2229 	 *		synced to the VBLANK, and computes the typical number of cycles per interrupt
2230 	 */
2231 
2232 	/* start the CPU interrupt timers */
2233 	for (i = 0; i < totalcpu; i++)
2234 	{
2235 		ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2236 
2237 		/* remove old timers */
2238 		if (cpu[i].vblankint_timer)
2239 			timer_remove(cpu[i].vblankint_timer);
2240 		if (cpu[i].timedint_timer)
2241 			timer_remove(cpu[i].timedint_timer);
2242 
2243 		/* compute the average number of cycles per interrupt */
2244 		if (ipf <= 0)
2245 			ipf = 1;
2246 		cpu[i].vblankint_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf);
2247 		cpu[i].vblankint_timer = timer_set(TIME_NEVER, 0, NULL);
2248 
2249 		/* see if we need to allocate a CPU timer */
2250 		ipf = Machine->drv->cpu[i].timed_interrupts_per_second;
2251 		if (ipf)
2252 		{
2253 			cpu[i].timedint_period = cpu_computerate(ipf);
2254 			cpu[i].timedint_timer = timer_pulse(cpu[i].timedint_period, i, cpu_timedintcallback);
2255 		}
2256 	}
2257 
2258 	/* note that since we start the first frame on the refresh, we can't pulse starting
2259 	   immediately; instead, we back up one VBLANK period, and inch forward until we hit
2260 	   positive time. That time will be the time of the first VBLANK timer callback */
2261 	timer_remove(vblank_timer);
2262 
2263 	first_time = -TIME_IN_USEC(Machine->drv->vblank_duration) + vblank_period;
2264 	while (first_time < 0)
2265 	{
2266 		cpu_vblankcallback(-1);
2267 		first_time += vblank_period;
2268 	}
2269 	vblank_timer = timer_set(first_time, 0, cpu_firstvblankcallback);
2270 }
2271 
2272 
2273 /* AJP 981016 */
cpu_is_saving_context(int _activecpu)2274 int cpu_is_saving_context(int _activecpu)
2275 {
2276 	return (cpu[_activecpu].save_context);
2277 }
2278 
2279 
2280 /* JB 971019 */
cpu_getcontext(int _activecpu)2281 void* cpu_getcontext(int _activecpu)
2282 {
2283 	return cpu[_activecpu].context;
2284 }
2285 
2286 
2287 /***************************************************************************
2288   Retrieve or set the entire context of the active CPU
2289 ***************************************************************************/
2290 
cpu_get_context(void * context)2291 unsigned cpu_get_context(void *context)
2292 {
2293 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2294 	return GETCONTEXT(cpunum,context);
2295 }
2296 
cpu_set_context(void * context)2297 void cpu_set_context(void *context)
2298 {
2299 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2300 	SETCONTEXT(cpunum,context);
2301 }
2302 
2303 /***************************************************************************
2304   Retrieve or set a cycle counts lookup table for the active CPU
2305 ***************************************************************************/
2306 
cpu_get_cycle_table(int which)2307 void *cpu_get_cycle_table(int which)
2308 {
2309 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2310 	return GETCYCLETBL(cpunum,which);
2311 }
2312 
cpu_set_cycle_tbl(int which,void * new_table)2313 void cpu_set_cycle_tbl(int which, void *new_table)
2314 {
2315 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2316 	SETCYCLETBL(cpunum,which,new_table);
2317 }
2318 
2319 /***************************************************************************
2320   Retrieve or set the value of a specific register of the active CPU
2321 ***************************************************************************/
2322 
cpu_get_reg(int regnum)2323 unsigned cpu_get_reg(int regnum)
2324 {
2325 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2326 	return GETREG(cpunum,regnum);
2327 }
2328 
cpu_set_reg(int regnum,unsigned val)2329 void cpu_set_reg(int regnum, unsigned val)
2330 {
2331 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2332 	SETREG(cpunum,regnum,val);
2333 }
2334 
2335 /***************************************************************************
2336 
2337   Get various CPU information
2338 
2339 ***************************************************************************/
2340 
2341 /***************************************************************************
2342   Returns the number of address bits for the active CPU
2343 ***************************************************************************/
cpu_address_bits(void)2344 unsigned cpu_address_bits(void)
2345 {
2346 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2347 	return cpuintf[CPU_TYPE(cpunum)].address_bits;
2348 }
2349 
2350 /***************************************************************************
2351   Returns the address bit mask for the active CPU
2352 ***************************************************************************/
cpu_address_mask(void)2353 unsigned cpu_address_mask(void)
2354 {
2355 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2356 	return (1 << cpuintf[CPU_TYPE(cpunum)].address_bits) - 1;
2357 }
2358 
2359 /***************************************************************************
2360   Returns the address shift factor for the active CPU
2361 ***************************************************************************/
cpu_address_shift(void)2362 int cpu_address_shift(void)
2363 {
2364 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2365 	return cpuintf[CPU_TYPE(cpunum)].address_shift;
2366 }
2367 
2368 /***************************************************************************
2369   Returns the endianess for the active CPU
2370 ***************************************************************************/
cpu_endianess(void)2371 unsigned cpu_endianess(void)
2372 {
2373 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2374 	return cpuintf[CPU_TYPE(cpunum)].endianess;
2375 }
2376 
2377 /***************************************************************************
2378   Returns the code align unit for the active CPU (1 byte, 2 word, ...)
2379 ***************************************************************************/
cpu_align_unit(void)2380 unsigned cpu_align_unit(void)
2381 {
2382 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2383 	return cpuintf[CPU_TYPE(cpunum)].align_unit;
2384 }
2385 
2386 /***************************************************************************
2387   Returns the max. instruction length for the active CPU
2388 ***************************************************************************/
cpu_max_inst_len(void)2389 unsigned cpu_max_inst_len(void)
2390 {
2391 	int cpunum = (activecpu < 0) ? 0 : activecpu;
2392 	return cpuintf[CPU_TYPE(cpunum)].max_inst_len;
2393 }
2394 
2395 /***************************************************************************
2396   Returns the name for the active CPU
2397 ***************************************************************************/
cpu_name(void)2398 const char *cpu_name(void)
2399 {
2400 	if( activecpu >= 0 )
2401 		return CPUINFO(activecpu,NULL,CPU_INFO_NAME);
2402 	return "";
2403 }
2404 
2405 /***************************************************************************
2406   Returns the family name for the active CPU
2407 ***************************************************************************/
cpu_core_family(void)2408 const char *cpu_core_family(void)
2409 {
2410 	if( activecpu >= 0 )
2411 		return CPUINFO(activecpu,NULL,CPU_INFO_FAMILY);
2412 	return "";
2413 }
2414 
2415 /***************************************************************************
2416   Returns the version number for the active CPU
2417 ***************************************************************************/
cpu_core_version(void)2418 const char *cpu_core_version(void)
2419 {
2420 	if( activecpu >= 0 )
2421 		return CPUINFO(activecpu,NULL,CPU_INFO_VERSION);
2422 	return "";
2423 }
2424 
2425 /***************************************************************************
2426   Returns the core filename for the active CPU
2427 ***************************************************************************/
cpu_core_file(void)2428 const char *cpu_core_file(void)
2429 {
2430 	if( activecpu >= 0 )
2431 		return CPUINFO(activecpu,NULL,CPU_INFO_FILE);
2432 	return "";
2433 }
2434 
2435 /***************************************************************************
2436   Returns the credits for the active CPU
2437 ***************************************************************************/
cpu_core_credits(void)2438 const char *cpu_core_credits(void)
2439 {
2440 	if( activecpu >= 0 )
2441 		return CPUINFO(activecpu,NULL,CPU_INFO_CREDITS);
2442 	return "";
2443 }
2444 
2445 /***************************************************************************
2446   Returns a dissassembled instruction for the active CPU
2447 ***************************************************************************/
cpu_dasm(char * buffer,unsigned pc)2448 unsigned cpu_dasm(char *buffer, unsigned pc)
2449 {
2450 	if( activecpu >= 0 )
2451 		return CPUDASM(activecpu,buffer,pc);
2452 	return 0;
2453 }
2454 
2455 /***************************************************************************
2456   Returns a flags (state, condition codes) string for the active CPU
2457 ***************************************************************************/
cpu_flags(void)2458 const char *cpu_flags(void)
2459 {
2460 	if( activecpu >= 0 )
2461 		return CPUINFO(activecpu,NULL,CPU_INFO_FLAGS);
2462 	return "";
2463 }
2464 
2465 /***************************************************************************
2466   Returns the number of address bits for a specific CPU type
2467 ***************************************************************************/
cputype_address_bits(int cpu_type)2468 unsigned cputype_address_bits(int cpu_type)
2469 {
2470 	cpu_type &= ~CPU_FLAGS_MASK;
2471 	if( cpu_type < CPU_COUNT )
2472 		return cpuintf[cpu_type].address_bits;
2473 	return 0;
2474 }
2475 
2476 /***************************************************************************
2477   Returns the address bit mask for a specific CPU type
2478 ***************************************************************************/
cputype_address_mask(int cpu_type)2479 unsigned cputype_address_mask(int cpu_type)
2480 {
2481 	cpu_type &= ~CPU_FLAGS_MASK;
2482 	if( cpu_type < CPU_COUNT )
2483 		return (1 << cpuintf[cpu_type].address_bits) - 1;
2484 	return 0;
2485 }
2486 
2487 /***************************************************************************
2488   Returns the address shift factor for a specific CPU type
2489 ***************************************************************************/
cputype_address_shift(int cpu_type)2490 int cputype_address_shift(int cpu_type)
2491 {
2492 	cpu_type &= ~CPU_FLAGS_MASK;
2493 	if( cpu_type < CPU_COUNT )
2494 		return cpuintf[cpu_type].address_shift;
2495 	return 0;
2496 }
2497 
2498 /***************************************************************************
2499   Returns the endianess for a specific CPU type
2500 ***************************************************************************/
cputype_endianess(int cpu_type)2501 unsigned cputype_endianess(int cpu_type)
2502 {
2503 	cpu_type &= ~CPU_FLAGS_MASK;
2504 	if( cpu_type < CPU_COUNT )
2505 		return cpuintf[cpu_type].endianess;
2506 	return 0;
2507 }
2508 
2509 /***************************************************************************
2510   Returns the code align unit for a speciific CPU type (1 byte, 2 word, ...)
2511 ***************************************************************************/
cputype_align_unit(int cpu_type)2512 unsigned cputype_align_unit(int cpu_type)
2513 {
2514 	cpu_type &= ~CPU_FLAGS_MASK;
2515 	if( cpu_type < CPU_COUNT )
2516 		return cpuintf[cpu_type].align_unit;
2517 	return 0;
2518 }
2519 
2520 /***************************************************************************
2521   Returns the max. instruction length for a specific CPU type
2522 ***************************************************************************/
cputype_max_inst_len(int cpu_type)2523 unsigned cputype_max_inst_len(int cpu_type)
2524 {
2525 	cpu_type &= ~CPU_FLAGS_MASK;
2526 	if( cpu_type < CPU_COUNT )
2527 		return cpuintf[cpu_type].max_inst_len;
2528 	return 0;
2529 }
2530 
2531 /***************************************************************************
2532   Returns the name for a specific CPU type
2533 ***************************************************************************/
cputype_name(int cpu_type)2534 const char *cputype_name(int cpu_type)
2535 {
2536 	cpu_type &= ~CPU_FLAGS_MASK;
2537 	if( cpu_type < CPU_COUNT )
2538 		return IFC_INFO(cpu_type,NULL,CPU_INFO_NAME);
2539 	return "";
2540 }
2541 
2542 /***************************************************************************
2543   Returns the family name for a specific CPU type
2544 ***************************************************************************/
cputype_core_family(int cpu_type)2545 const char *cputype_core_family(int cpu_type)
2546 {
2547 	cpu_type &= ~CPU_FLAGS_MASK;
2548 	if( cpu_type < CPU_COUNT )
2549 		return IFC_INFO(cpu_type,NULL,CPU_INFO_FAMILY);
2550 	return "";
2551 }
2552 
2553 /***************************************************************************
2554   Returns the version number for a specific CPU type
2555 ***************************************************************************/
cputype_core_version(int cpu_type)2556 const char *cputype_core_version(int cpu_type)
2557 {
2558 	cpu_type &= ~CPU_FLAGS_MASK;
2559 	if( cpu_type < CPU_COUNT )
2560 		return IFC_INFO(cpu_type,NULL,CPU_INFO_VERSION);
2561 	return "";
2562 }
2563 
2564 /***************************************************************************
2565   Returns the core filename for a specific CPU type
2566 ***************************************************************************/
cputype_core_file(int cpu_type)2567 const char *cputype_core_file(int cpu_type)
2568 {
2569 	cpu_type &= ~CPU_FLAGS_MASK;
2570 	if( cpu_type < CPU_COUNT )
2571 		return IFC_INFO(cpu_type,NULL,CPU_INFO_FILE);
2572 	return "";
2573 }
2574 
2575 /***************************************************************************
2576   Returns the credits for a specific CPU type
2577 ***************************************************************************/
cputype_core_credits(int cpu_type)2578 const char *cputype_core_credits(int cpu_type)
2579 {
2580 	cpu_type &= ~CPU_FLAGS_MASK;
2581 	if( cpu_type < CPU_COUNT )
2582 		return IFC_INFO(cpu_type,NULL,CPU_INFO_CREDITS);
2583 	return "";
2584 }
2585 
2586 /***************************************************************************
2587   Returns the number of address bits for a specific CPU number
2588 ***************************************************************************/
cpunum_address_bits(int cpunum)2589 unsigned cpunum_address_bits(int cpunum)
2590 {
2591 	if( cpunum < totalcpu )
2592 		return cputype_address_bits(CPU_TYPE(cpunum));
2593 	return 0;
2594 }
2595 
2596 /***************************************************************************
2597   Returns the address bit mask for a specific CPU number
2598 ***************************************************************************/
cpunum_address_mask(int cpunum)2599 unsigned cpunum_address_mask(int cpunum)
2600 {
2601 	if( cpunum < totalcpu )
2602 		return cputype_address_mask(CPU_TYPE(cpunum));
2603 	return 0;
2604 }
2605 
2606 /***************************************************************************
2607   Returns the endianess for a specific CPU number
2608 ***************************************************************************/
cpunum_endianess(int cpunum)2609 unsigned cpunum_endianess(int cpunum)
2610 {
2611 	if( cpunum < totalcpu )
2612 		return cputype_endianess(CPU_TYPE(cpunum));
2613 	return 0;
2614 }
2615 
2616 /***************************************************************************
2617   Returns the code align unit for the active CPU (1 byte, 2 word, ...)
2618 ***************************************************************************/
cpunum_align_unit(int cpunum)2619 unsigned cpunum_align_unit(int cpunum)
2620 {
2621 	if( cpunum < totalcpu )
2622 		return cputype_align_unit(CPU_TYPE(cpunum));
2623 	return 0;
2624 }
2625 
2626 /***************************************************************************
2627   Returns the max. instruction length for a specific CPU number
2628 ***************************************************************************/
cpunum_max_inst_len(int cpunum)2629 unsigned cpunum_max_inst_len(int cpunum)
2630 {
2631 	if( cpunum < totalcpu )
2632 		return cputype_max_inst_len(CPU_TYPE(cpunum));
2633 	return 0;
2634 }
2635 
2636 /***************************************************************************
2637   Returns the name for a specific CPU number
2638 ***************************************************************************/
cpunum_name(int cpunum)2639 const char *cpunum_name(int cpunum)
2640 {
2641 	if( cpunum < totalcpu )
2642 		return cputype_name(CPU_TYPE(cpunum));
2643 	return "";
2644 }
2645 
2646 /***************************************************************************
2647   Returns the family name for a specific CPU number
2648 ***************************************************************************/
cpunum_core_family(int cpunum)2649 const char *cpunum_core_family(int cpunum)
2650 {
2651 	if( cpunum < totalcpu )
2652 		return cputype_core_family(CPU_TYPE(cpunum));
2653 	return "";
2654 }
2655 
2656 /***************************************************************************
2657   Returns the core version for a specific CPU number
2658 ***************************************************************************/
cpunum_core_version(int cpunum)2659 const char *cpunum_core_version(int cpunum)
2660 {
2661 	if( cpunum < totalcpu )
2662 		return cputype_core_version(CPU_TYPE(cpunum));
2663 	return "";
2664 }
2665 
2666 /***************************************************************************
2667   Returns the core filename for a specific CPU number
2668 ***************************************************************************/
cpunum_core_file(int cpunum)2669 const char *cpunum_core_file(int cpunum)
2670 {
2671 	if( cpunum < totalcpu )
2672 		return cputype_core_file(CPU_TYPE(cpunum));
2673 	return "";
2674 }
2675 
2676 /***************************************************************************
2677   Returns the credits for a specific CPU number
2678 ***************************************************************************/
cpunum_core_credits(int cpunum)2679 const char *cpunum_core_credits(int cpunum)
2680 {
2681 	if( cpunum < totalcpu )
2682 		return cputype_core_credits(CPU_TYPE(cpunum));
2683 	return "";
2684 }
2685 
2686 /***************************************************************************
2687   Return a register value for a specific CPU number of the running machine
2688 ***************************************************************************/
cpunum_get_reg(int cpunum,int regnum)2689 unsigned cpunum_get_reg(int cpunum, int regnum)
2690 {
2691 	int oldactive;
2692 	unsigned val = 0;
2693 
2694 	if( cpunum == activecpu )
2695 		return cpu_get_reg( regnum );
2696 
2697 	/* swap to the CPU's context */
2698 	if (activecpu >= 0)
2699 		if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2700 	oldactive = activecpu;
2701 	activecpu = cpunum;
2702 	memorycontextswap(activecpu);
2703 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2704 
2705 	val = GETREG(activecpu,regnum);
2706 
2707 	/* update the CPU's context */
2708 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2709 	activecpu = oldactive;
2710 	if (activecpu >= 0)
2711 	{
2712 		memorycontextswap(activecpu);
2713 		if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2714 	}
2715 
2716 	return val;
2717 }
2718 
2719 /***************************************************************************
2720   Set a register value for a specific CPU number of the running machine
2721 ***************************************************************************/
cpunum_set_reg(int cpunum,int regnum,unsigned val)2722 void cpunum_set_reg(int cpunum, int regnum, unsigned val)
2723 {
2724 	int oldactive;
2725 
2726 	if( cpunum == activecpu )
2727 	{
2728 		cpu_set_reg( regnum, val );
2729 		return;
2730 	}
2731 
2732 	/* swap to the CPU's context */
2733 	if (activecpu >= 0)
2734 		if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2735 	oldactive = activecpu;
2736 	activecpu = cpunum;
2737 	memorycontextswap(activecpu);
2738 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2739 
2740 	SETREG(activecpu,regnum,val);
2741 
2742 	/* update the CPU's context */
2743 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2744 	activecpu = oldactive;
2745 	if (activecpu >= 0)
2746 	{
2747 		memorycontextswap(activecpu);
2748 		if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2749 	}
2750 }
2751 
2752 /***************************************************************************
2753   Return a dissassembled instruction for a specific CPU
2754 ***************************************************************************/
cpunum_dasm(int cpunum,char * buffer,unsigned pc)2755 unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc)
2756 {
2757 	unsigned result;
2758 	int oldactive;
2759 
2760 	if( cpunum == activecpu )
2761 		return cpu_dasm(buffer,pc);
2762 
2763 	/* swap to the CPU's context */
2764 	if (activecpu >= 0)
2765 		if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2766 	oldactive = activecpu;
2767 	activecpu = cpunum;
2768 	memorycontextswap(activecpu);
2769 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2770 
2771 	result = CPUDASM(activecpu,buffer,pc);
2772 
2773 	/* update the CPU's context */
2774 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2775 	activecpu = oldactive;
2776 	if (activecpu >= 0)
2777 	{
2778 		memorycontextswap(activecpu);
2779 		if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2780 	}
2781 
2782 	return result;
2783 }
2784 
2785 /***************************************************************************
2786   Return a flags (state, condition codes) string for a specific CPU
2787 ***************************************************************************/
cpunum_flags(int cpunum)2788 const char *cpunum_flags(int cpunum)
2789 {
2790 	const char *result;
2791 	int oldactive;
2792 
2793 	if( cpunum == activecpu )
2794 		return cpu_flags();
2795 
2796 	/* swap to the CPU's context */
2797 	if (activecpu >= 0)
2798 		if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2799 	oldactive = activecpu;
2800 	activecpu = cpunum;
2801 	memorycontextswap(activecpu);
2802 	if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2803 
2804 	result = CPUINFO(activecpu,NULL,CPU_INFO_FLAGS);
2805 
2806 	/* update the CPU's context */
2807 	if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2808 	activecpu = oldactive;
2809 	if (activecpu >= 0)
2810 	{
2811 		memorycontextswap(activecpu);
2812 		if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2813 	}
2814 
2815 	return result;
2816 }
2817 
2818 /***************************************************************************
2819 
2820   Dummy interfaces for non-CPUs
2821 
2822 ***************************************************************************/
Dummy_reset(void * param)2823 static void Dummy_reset(void *param) { }
Dummy_exit(void)2824 static void Dummy_exit(void) { }
Dummy_execute(int cycles)2825 static int Dummy_execute(int cycles) { return cycles; }
2826 //static void Dummy_burn(int cycles) { }
Dummy_get_context(void * regs)2827 static unsigned Dummy_get_context(void *regs) { return 0; }
Dummy_set_context(void * regs)2828 static void Dummy_set_context(void *regs) { }
Dummy_get_pc(void)2829 static unsigned Dummy_get_pc(void) { return 0; }
Dummy_set_pc(unsigned val)2830 static void Dummy_set_pc(unsigned val) { }
Dummy_get_sp(void)2831 static unsigned Dummy_get_sp(void) { return 0; }
Dummy_set_sp(unsigned val)2832 static void Dummy_set_sp(unsigned val) { }
Dummy_get_reg(int regnum)2833 static unsigned Dummy_get_reg(int regnum) { return 0; }
Dummy_set_reg(int regnum,unsigned val)2834 static void Dummy_set_reg(int regnum, unsigned val) { }
Dummy_set_nmi_line(int state)2835 static void Dummy_set_nmi_line(int state) { }
Dummy_set_irq_line(int irqline,int state)2836 static void Dummy_set_irq_line(int irqline, int state) { }
Dummy_set_irq_callback(int (* callback)(int irqline))2837 static void Dummy_set_irq_callback(int (*callback)(int irqline)) { }
2838 
2839 /****************************************************************************
2840  * Return a formatted string for a register
2841  ****************************************************************************/
Dummy_info(void * context,int regnum)2842 static const char *Dummy_info(void *context, int regnum)
2843 {
2844 	if( !context && regnum )
2845 		return "";
2846 
2847 	switch (regnum)
2848 	{
2849 		case CPU_INFO_NAME: return "Dummy";
2850 		case CPU_INFO_FAMILY: return "no CPU";
2851 		case CPU_INFO_VERSION: return "0.0";
2852 		case CPU_INFO_FILE: return __FILE__;
2853 		case CPU_INFO_CREDITS: return "The MAME team.";
2854 	}
2855 	return "";
2856 }
2857 
Dummy_dasm(char * buffer,unsigned pc)2858 static unsigned Dummy_dasm(char *buffer, unsigned pc)
2859 {
2860 	strcpy(buffer, "???");
2861 	return 1;
2862 }
2863 
2864