1 /*****************************************************************************
2  *
3  *	 m6502.c
4  *	 Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2
5  *
6  *	 Copyright (c) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
7  *	 65sc02 core Copyright (c) 2000 Peter Trauner.
8  *
9  *	 - This source code is released as freeware for non-commercial purposes.
10  *	 - You are free to use and redistribute this code in modified or
11  *	   unmodified form, provided you list me in the credits.
12  *	 - If you modify this source code, you must add a notice to each modified
13  *	   source file that it has been changed.  If you're a nice person, you
14  *	   will clearly mark each change too.  :)
15  *	 - If you wish to use this for commercial purposes, please contact me at
16  *	   pullmoll@t-online.de
17  *	 - The author of this copywritten work reserves the right to change the
18  *	   terms of its usage and license at any time, including retroactively
19  *	 - This entire notice must remain in the source code.
20  *
21  *****************************************************************************/
22 /* 2.February 2000 PeT added 65sc02 subtype */
23 /* 10.March   2000 PeT added 6502 set overflow input line */
24 
25 #include <stdio.h>
26 #include "driver.h"
27 #include "state.h"
28 #include "m6502.h"
29 #include "ops02.h"
30 #include "ill02.h"
31 
32 
33 #define VERBOSE 0
34 
35 #if VERBOSE
36 #define LOG(x)	logerror x
37 #else
38 #define LOG(x)
39 #endif
40 
41 /****************************************************************************
42  * The 6502 registers.
43  ****************************************************************************/
44 typedef struct
45 {
46 	UINT8	subtype;		/* currently selected cpu sub type */
47 	void	(**insn)(void); /* pointer to the function pointer table */
48 	PAIR	ppc;			/* previous program counter */
49 	PAIR	pc; 			/* program counter */
50 	PAIR	sp; 			/* stack pointer (always 100 - 1FF) */
51 	PAIR	zp; 			/* zero page address */
52 	PAIR	ea; 			/* effective address */
53 	UINT8	a;				/* Accumulator */
54 	UINT8	x;				/* X index register */
55 	UINT8	y;				/* Y index register */
56 	UINT8	p;				/* Processor status */
57 	UINT8	pending_irq;	/* nonzero if an IRQ is pending */
58 	UINT8	after_cli;		/* pending IRQ and last insn cleared I */
59 	UINT8	nmi_state;
60 	UINT8	irq_state;
61 	UINT8   so_state;
62 	int 	(*irq_callback)(int irqline);	/* IRQ callback */
63 }	m6502_Regs;
64 
65 int m6502_ICount = 0;
66 
67 static m6502_Regs m6502;
68 
69 /***************************************************************
70  * include the opcode macros, functions and tables
71  ***************************************************************/
72 #include "t6502.c"
73 
74 #if (HAS_M6510)
75 #include "t6510.c"
76 #endif
77 
78 #include "opsc02.h"
79 
80 #if (HAS_M65C02)
81 #include "t65c02.c"
82 #endif
83 
84 #if (HAS_M65SC02)
85 #include "t65sc02.c"
86 #endif
87 
88 #if (HAS_N2A03)
89 #include "tn2a03.c"
90 #endif
91 
92 /*****************************************************************************
93  *
94  *		6502 CPU interface functions
95  *
96  *****************************************************************************/
97 
m6502_reset(void * param)98 void m6502_reset(void *param)
99 {
100 	m6502.subtype = SUBTYPE_6502;
101 	m6502.insn = insn6502;
102 
103 	/* wipe out the rest of the m6502 structure */
104 	/* read the reset vector into PC */
105 	PCL = RDMEM(M6502_RST_VEC);
106 	PCH = RDMEM(M6502_RST_VEC+1);
107 
108 	m6502.sp.d = 0x01ff;	/* stack pointer starts at page 1 offset FF */
109 	m6502.p = F_T|F_I|F_Z|F_B|(P&F_D);	/* set T, I and Z flags */
110 	m6502.pending_irq = 0;	/* nonzero if an IRQ is pending */
111 	m6502.after_cli = 0;	/* pending IRQ and last insn cleared I */
112 	m6502.irq_callback = NULL;
113 
114 	change_pc16(PCD);
115 }
116 
m6502_exit(void)117 void m6502_exit(void)
118 {
119 	/* nothing to do yet */
120 }
121 
m6502_get_context(void * dst)122 unsigned m6502_get_context (void *dst)
123 {
124 	if( dst )
125 		*(m6502_Regs*)dst = m6502;
126 	return sizeof(m6502_Regs);
127 }
128 
m6502_set_context(void * src)129 void m6502_set_context (void *src)
130 {
131 	if( src )
132 	{
133 		m6502 = *(m6502_Regs*)src;
134 		change_pc(PCD);
135 	}
136 }
137 
m6502_get_pc(void)138 unsigned m6502_get_pc (void)
139 {
140 	return PCD;
141 }
142 
m6502_set_pc(unsigned val)143 void m6502_set_pc (unsigned val)
144 {
145 	PCW = val;
146 	change_pc(PCD);
147 }
148 
m6502_get_sp(void)149 unsigned m6502_get_sp (void)
150 {
151 	return S;
152 }
153 
m6502_set_sp(unsigned val)154 void m6502_set_sp (unsigned val)
155 {
156 	S = val;
157 }
158 
m6502_get_reg(int regnum)159 unsigned m6502_get_reg (int regnum)
160 {
161 	switch( regnum )
162 	{
163 		case M6502_PC: return m6502.pc.w.l;
164 		case M6502_S: return m6502.sp.b.l;
165 		case M6502_P: return m6502.p;
166 		case M6502_A: return m6502.a;
167 		case M6502_X: return m6502.x;
168 		case M6502_Y: return m6502.y;
169 		case M6502_EA: return m6502.ea.w.l;
170 		case M6502_ZP: return m6502.zp.w.l;
171 		case M6502_NMI_STATE: return m6502.nmi_state;
172 		case M6502_IRQ_STATE: return m6502.irq_state;
173 		case M6502_SO_STATE: return m6502.so_state;
174 		case M6502_SUBTYPE: return m6502.subtype;
175 		case REG_PREVIOUSPC: return m6502.ppc.w.l;
176 		default:
177 			if( regnum <= REG_SP_CONTENTS )
178 			{
179 				unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
180 				if( offset < 0x1ff )
181 					return RDMEM( offset ) | ( RDMEM( offset + 1 ) << 8 );
182 			}
183 	}
184 	return 0;
185 }
186 
m6502_set_reg(int regnum,unsigned val)187 void m6502_set_reg (int regnum, unsigned val)
188 {
189 	switch( regnum )
190 	{
191 		case M6502_PC: m6502.pc.w.l = val; break;
192 		case M6502_S: m6502.sp.b.l = val; break;
193 		case M6502_P: m6502.p = val; break;
194 		case M6502_A: m6502.a = val; break;
195 		case M6502_X: m6502.x = val; break;
196 		case M6502_Y: m6502.y = val; break;
197 		case M6502_EA: m6502.ea.w.l = val; break;
198 		case M6502_ZP: m6502.zp.w.l = val; break;
199 		case M6502_NMI_STATE: m6502_set_nmi_line( val ); break;
200 		case M6502_IRQ_STATE: m6502_set_irq_line( 0, val ); break;
201 		case M6502_SO_STATE: m6502_set_irq_line( M6502_SET_OVERFLOW, val ); break;
202 		default:
203 			if( regnum <= REG_SP_CONTENTS )
204 			{
205 				unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
206 				if( offset < 0x1ff )
207 				{
208 					WRMEM( offset, val & 0xfff );
209 					WRMEM( offset + 1, (val >> 8) & 0xff );
210 				}
211 			}
212 	}
213 }
214 
m6502_take_irq(void)215 static INLINE void m6502_take_irq(void)
216 {
217 	if( !(P & F_I) )
218 	{
219 		EAD = M6502_IRQ_VEC;
220 		m6502_ICount -= 7;
221 		PUSH(PCH);
222 		PUSH(PCL);
223 		PUSH(P & ~F_B);
224 		P |= F_I;		/* set I flag */
225 		PCL = RDMEM(EAD);
226 		PCH = RDMEM(EAD+1);
227 		LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
228 		/* call back the cpuintrf to let it clear the line */
229 		if (m6502.irq_callback) (*m6502.irq_callback)(0);
230 		change_pc16(PCD);
231 	}
232 	m6502.pending_irq = 0;
233 }
234 
m6502_execute(int cycles)235 int m6502_execute(int cycles)
236 {
237 	m6502_ICount = cycles;
238 
239 	change_pc16(PCD);
240 
241 	do
242 	{
243 		UINT8 op;
244 		PPC = PCD;
245 
246 #if 1
247 		/* if an irq is pending, take it now */
248 		if( m6502.pending_irq )
249 			m6502_take_irq();
250 
251 		op = RDOP();
252 		(*m6502.insn[op])();
253 #else
254 		/* thought as irq request while executing sei */
255         /* sei sets I flag on the stack*/
256 		op = RDOP();
257 
258 		/* if an irq is pending, take it now */
259 		if( m6502.pending_irq && (op == 0x78) )
260 			m6502_take_irq();
261 
262 		(*m6502.insn[op])();
263 #endif
264 
265 		/* check if the I flag was just reset (interrupts enabled) */
266 		if( m6502.after_cli )
267 		{
268 			LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
269 			m6502.after_cli = 0;
270 			if (m6502.irq_state != CLEAR_LINE)
271 			{
272 				LOG((": irq line is asserted: set pending IRQ\n"));
273 				m6502.pending_irq = 1;
274 			}
275 			else
276 			{
277 				LOG((": irq line is clear\n"));
278 			}
279 		}
280 		else
281 		if( m6502.pending_irq )
282 			m6502_take_irq();
283 
284 	} while (m6502_ICount > 0);
285 
286 	return cycles - m6502_ICount;
287 }
288 
m6502_set_nmi_line(int state)289 void m6502_set_nmi_line(int state)
290 {
291 	if (m6502.nmi_state == state) return;
292 	m6502.nmi_state = state;
293 	if( state != CLEAR_LINE )
294 	{
295 		LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
296 		EAD = M6502_NMI_VEC;
297 		m6502_ICount -= 7;
298 		PUSH(PCH);
299 		PUSH(PCL);
300 		PUSH(P & ~F_B);
301 		P |= F_I;		/* set I flag */
302 		PCL = RDMEM(EAD);
303 		PCH = RDMEM(EAD+1);
304 		LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
305 		change_pc16(PCD);
306 	}
307 }
308 
m6502_set_irq_line(int irqline,int state)309 void m6502_set_irq_line(int irqline, int state)
310 {
311 	if( irqline == M6502_SET_OVERFLOW )
312 	{
313 		if( m6502.so_state && !state )
314 		{
315 			LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
316 			P|=F_V;
317 		}
318 		m6502.so_state=state;
319 		return;
320 	}
321 	m6502.irq_state = state;
322 	if( state != CLEAR_LINE )
323 	{
324 		LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
325 		m6502.pending_irq = 1;
326 	}
327 }
328 
m6502_set_irq_callback(int (* callback)(int))329 void m6502_set_irq_callback(int (*callback)(int))
330 {
331 	m6502.irq_callback = callback;
332 }
333 
m6502_state_save(void * file)334 void m6502_state_save(void *file)
335 {
336 	int cpu = cpu_getactivecpu();
337 	state_save_UINT8(file,"m6502",cpu,"TYPE",&m6502.subtype,1);
338 	/* insn is set at restore since it's a pointer */
339 	state_save_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
340 	state_save_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
341 	state_save_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
342 	state_save_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
343 	state_save_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
344 	state_save_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
345 	state_save_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
346 	state_save_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
347 	state_save_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
348 	state_save_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
349 	state_save_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
350 }
351 
m6502_state_load(void * file)352 void m6502_state_load(void *file)
353 {
354 	int cpu = cpu_getactivecpu();
355 	state_load_UINT8(file,"m6502",cpu,"TYPE",&m6502.subtype,1);
356 	/* insn is set at restore since it's a pointer */
357 	switch (m6502.subtype)
358 	{
359 #if (HAS_M65C02)
360 		case SUBTYPE_65C02:
361 			m6502.insn = insn65c02;
362 			break;
363 #endif
364 #if (HAS_M65SC02)
365 		case SUBTYPE_65SC02:
366 			m6502.insn = insn65sc02;
367 			break;
368 #endif
369 #if (HAS_M6510)
370 		case SUBTYPE_6510:
371 			m6502.insn = insn6510;
372 			break;
373 #endif
374 		default:
375 			m6502.insn = insn6502;
376 			break;
377 	}
378 	state_load_UINT16(file,"m6502",cpu,"PC",&m6502.pc.w.l,2);
379 	state_load_UINT16(file,"m6502",cpu,"SP",&m6502.sp.w.l,2);
380 	state_load_UINT8(file,"m6502",cpu,"P",&m6502.p,1);
381 	state_load_UINT8(file,"m6502",cpu,"A",&m6502.a,1);
382 	state_load_UINT8(file,"m6502",cpu,"X",&m6502.x,1);
383 	state_load_UINT8(file,"m6502",cpu,"Y",&m6502.y,1);
384 	state_load_UINT8(file,"m6502",cpu,"PENDING",&m6502.pending_irq,1);
385 	state_load_UINT8(file,"m6502",cpu,"AFTER_CLI",&m6502.after_cli,1);
386 	state_load_UINT8(file,"m6502",cpu,"NMI_STATE",&m6502.nmi_state,1);
387 	state_load_UINT8(file,"m6502",cpu,"IRQ_STATE",&m6502.irq_state,1);
388 	state_load_UINT8(file,"m6502",cpu,"SO_STATE",&m6502.so_state,1);
389 }
390 
391 /****************************************************************************
392  * Return a formatted string for a register
393  ****************************************************************************/
m6502_info(void * context,int regnum)394 const char *m6502_info(void *context, int regnum)
395 {
396 	switch( regnum )
397 	{
398 		case CPU_INFO_NAME: return "M6502";
399 		case CPU_INFO_FAMILY: return "Motorola 6502";
400 		case CPU_INFO_VERSION: return "1.2";
401 		case CPU_INFO_FILE: return __FILE__;
402 		case CPU_INFO_CREDITS: return "Copyright (c) 1998 Juergen Buchmueller, all rights reserved.";
403 	}
404 	return "";
405 }
406 
m6502_dasm(char * buffer,unsigned pc)407 unsigned m6502_dasm(char *buffer, unsigned pc)
408 {
409 	sprintf( buffer, "$%02X", cpu_readop(pc) );
410 	return 1;
411 }
412 
413 /****************************************************************************
414  * 65C02 section
415  ****************************************************************************/
416 #if (HAS_M65C02)
417 
m65c02_reset(void * param)418 void m65c02_reset (void *param)
419 {
420 	m6502_reset(param);
421 	P &=~F_D;
422 	m6502.subtype = SUBTYPE_65C02;
423 	m6502.insn = insn65c02;
424 }
425 
m65c02_exit(void)426 void m65c02_exit  (void) { m6502_exit(); }
427 
m65c02_take_irq(void)428 static INLINE void m65c02_take_irq(void)
429 {
430 	if( !(P & F_I) )
431 	{
432 		EAD = M6502_IRQ_VEC;
433 		m6502_ICount -= 7;
434 		PUSH(PCH);
435 		PUSH(PCL);
436 		PUSH(P & ~F_B);
437 		P = (P & ~F_D) | F_I;		/* knock out D and set I flag */
438 		PCL = RDMEM(EAD);
439 		PCH = RDMEM(EAD+1);
440 		LOG(("M65c02#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
441 		/* call back the cpuintrf to let it clear the line */
442 		if (m6502.irq_callback) (*m6502.irq_callback)(0);
443 		change_pc16(PCD);
444 	}
445 	m6502.pending_irq = 0;
446 }
447 
m65c02_execute(int cycles)448 int m65c02_execute(int cycles)
449 {
450 	m6502_ICount = cycles;
451 
452 	change_pc16(PCD);
453 
454 	do
455 	{
456 		UINT8 op;
457 		PPC = PCD;
458 
459 		op = RDOP();
460 		(*m6502.insn[op])();
461 
462 		/* if an irq is pending, take it now */
463 		if( m6502.pending_irq )
464 			m65c02_take_irq();
465 
466 
467 		/* check if the I flag was just reset (interrupts enabled) */
468 		if( m6502.after_cli )
469 		{
470 			LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
471 			m6502.after_cli = 0;
472 			if (m6502.irq_state != CLEAR_LINE)
473 			{
474 				LOG((": irq line is asserted: set pending IRQ\n"));
475 				m6502.pending_irq = 1;
476 			}
477 			else
478 			{
479 				LOG((": irq line is clear\n"));
480 			}
481 		}
482 		else
483 		if( m6502.pending_irq )
484 			m65c02_take_irq();
485 
486 	} while (m6502_ICount > 0);
487 
488 	return cycles - m6502_ICount;
489 }
490 
m65c02_get_context(void * dst)491 unsigned m65c02_get_context (void *dst) { return m6502_get_context(dst); }
m65c02_set_context(void * src)492 void m65c02_set_context (void *src) { m6502_set_context(src); }
m65c02_get_pc(void)493 unsigned m65c02_get_pc (void) { return m6502_get_pc(); }
m65c02_set_pc(unsigned val)494 void m65c02_set_pc (unsigned val) { m6502_set_pc(val); }
m65c02_get_sp(void)495 unsigned m65c02_get_sp (void) { return m6502_get_sp(); }
m65c02_set_sp(unsigned val)496 void m65c02_set_sp (unsigned val) { m6502_set_sp(val); }
m65c02_get_reg(int regnum)497 unsigned m65c02_get_reg (int regnum) { return m6502_get_reg(regnum); }
m65c02_set_reg(int regnum,unsigned val)498 void m65c02_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
499 
m65c02_set_nmi_line(int state)500 void m65c02_set_nmi_line(int state)
501 {
502 	if (m6502.nmi_state == state) return;
503 	m6502.nmi_state = state;
504 	if( state != CLEAR_LINE )
505 	{
506 		LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
507 		EAD = M6502_NMI_VEC;
508 		m6502_ICount -= 7;
509 		PUSH(PCH);
510 		PUSH(PCL);
511 		PUSH(P & ~F_B);
512 		P = (P & ~F_D) | F_I;		/* knock out D and set I flag */
513 		PCL = RDMEM(EAD);
514 		PCH = RDMEM(EAD+1);
515 		LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
516 		change_pc16(PCD);
517 	}
518 }
519 
m65c02_set_irq_line(int irqline,int state)520 void m65c02_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
m65c02_set_irq_callback(int (* callback)(int irqline))521 void m65c02_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
m65c02_state_save(void * file)522 void m65c02_state_save(void *file) { m6502_state_save(file); }
m65c02_state_load(void * file)523 void m65c02_state_load(void *file) { m6502_state_load(file); }
m65c02_info(void * context,int regnum)524 const char *m65c02_info(void *context, int regnum)
525 {
526 	switch( regnum )
527 	{
528 		case CPU_INFO_NAME: return "M65C02";
529 		case CPU_INFO_VERSION: return "1.2";
530 	}
531 	return m6502_info(context,regnum);
532 }
m65c02_dasm(char * buffer,unsigned pc)533 unsigned m65c02_dasm(char *buffer, unsigned pc)
534 {
535 	sprintf( buffer, "$%02X", cpu_readop(pc) );
536 	return 1;
537 }
538 
539 #endif
540 
541 /****************************************************************************
542  * 65SC02 section
543  ****************************************************************************/
544 #if (HAS_M65SC02)
545 
m65sc02_reset(void * param)546 void m65sc02_reset (void *param)
547 {
548 	m6502_reset(param);
549 	m6502.subtype = SUBTYPE_65SC02;
550 	m6502.insn = insn65sc02;
551 }
m65sc02_exit(void)552 void m65sc02_exit  (void) { m6502_exit(); }
m65sc02_execute(int cycles)553 int  m65sc02_execute(int cycles) { return m65c02_execute(cycles); }
m65sc02_get_context(void * dst)554 unsigned m65sc02_get_context (void *dst) { return m6502_get_context(dst); }
m65sc02_set_context(void * src)555 void m65sc02_set_context (void *src) { m6502_set_context(src); }
m65sc02_get_pc(void)556 unsigned m65sc02_get_pc (void) { return m6502_get_pc(); }
m65sc02_set_pc(unsigned val)557 void m65sc02_set_pc (unsigned val) { m6502_set_pc(val); }
m65sc02_get_sp(void)558 unsigned m65sc02_get_sp (void) { return m6502_get_sp(); }
m65sc02_set_sp(unsigned val)559 void m65sc02_set_sp (unsigned val) { m6502_set_sp(val); }
m65sc02_get_reg(int regnum)560 unsigned m65sc02_get_reg (int regnum) { return m6502_get_reg(regnum); }
m65sc02_set_reg(int regnum,unsigned val)561 void m65sc02_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
m65sc02_set_nmi_line(int state)562 void m65sc02_set_nmi_line(int state) { m6502_set_nmi_line(state); }
m65sc02_set_irq_line(int irqline,int state)563 void m65sc02_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
m65sc02_set_irq_callback(int (* callback)(int irqline))564 void m65sc02_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
m65sc02_state_save(void * file)565 void m65sc02_state_save(void *file) { m6502_state_save(file); }
m65sc02_state_load(void * file)566 void m65sc02_state_load(void *file) { m6502_state_load(file); }
m65sc02_info(void * context,int regnum)567 const char *m65sc02_info(void *context, int regnum)
568 {
569 	switch( regnum )
570 	{
571 		case CPU_INFO_NAME: return "M65SC02";
572 		case CPU_INFO_FAMILY: return "Metal Oxid Semiconductor MOS 6502";
573 		case CPU_INFO_VERSION: return "1.0beta";
574 		case CPU_INFO_CREDITS:
575 			return "Copyright (c) 1998 Juergen Buchmueller\n"
576 				"Copyright (c) 2000 Peter Trauner\n"
577 				"all rights reserved.";
578 	}
579 	return m6502_info(context,regnum);
580 }
m65sc02_dasm(char * buffer,unsigned pc)581 unsigned m65sc02_dasm(char *buffer, unsigned pc)
582 {
583 	sprintf( buffer, "$%02X", cpu_readop(pc) );
584 	return 1;
585 }
586 
587 #endif
588 
589 /****************************************************************************
590  * 2A03 section
591  ****************************************************************************/
592 #if (HAS_N2A03)
593 
n2a03_reset(void * param)594 void n2a03_reset (void *param)
595 {
596 	m6502_reset(param);
597 	m6502.subtype = SUBTYPE_2A03;
598 	m6502.insn = insn2a03;
599 }
n2a03_exit(void)600 void n2a03_exit  (void) { m6502_exit(); }
n2a03_execute(int cycles)601 int  n2a03_execute(int cycles) { return m65c02_execute(cycles); }
n2a03_get_context(void * dst)602 unsigned n2a03_get_context (void *dst) { return m6502_get_context(dst); }
n2a03_set_context(void * src)603 void n2a03_set_context (void *src) { m6502_set_context(src); }
n2a03_get_pc(void)604 unsigned n2a03_get_pc (void) { return m6502_get_pc(); }
n2a03_set_pc(unsigned val)605 void n2a03_set_pc (unsigned val) { m6502_set_pc(val); }
n2a03_get_sp(void)606 unsigned n2a03_get_sp (void) { return m6502_get_sp(); }
n2a03_set_sp(unsigned val)607 void n2a03_set_sp (unsigned val) { m6502_set_sp(val); }
n2a03_get_reg(int regnum)608 unsigned n2a03_get_reg (int regnum) { return m6502_get_reg(regnum); }
n2a03_set_reg(int regnum,unsigned val)609 void n2a03_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
n2a03_set_nmi_line(int state)610 void n2a03_set_nmi_line(int state) { m6502_set_nmi_line(state); }
n2a03_set_irq_line(int irqline,int state)611 void n2a03_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
n2a03_set_irq_callback(int (* callback)(int irqline))612 void n2a03_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
n2a03_state_save(void * file)613 void n2a03_state_save(void *file) { m6502_state_save(file); }
n2a03_state_load(void * file)614 void n2a03_state_load(void *file) { m6502_state_load(file); }
n2a03_info(void * context,int regnum)615 const char *n2a03_info(void *context, int regnum)
616 {
617 	switch( regnum )
618 	{
619 		case CPU_INFO_NAME: return "N2A03";
620 		case CPU_INFO_VERSION: return "1.0";
621 	}
622 	return m6502_info(context,regnum);
623 }
624 
625 /* The N2A03 is integrally tied to its PSG (they're on the same die).
626    Bit 7 of address $4011 (the PSG's DPCM control register), when set,
627    causes an IRQ to be generated.  This function allows the IRQ to be called
628    from the PSG core when such an occasion arises. */
n2a03_irq(void)629 void n2a03_irq(void)
630 {
631   m65c02_take_irq();
632 }
633 
n2a03_dasm(char * buffer,unsigned pc)634 unsigned n2a03_dasm(char *buffer, unsigned pc)
635 {
636 	sprintf( buffer, "$%02X", cpu_readop(pc) );
637 	return 1;
638 }
639 #endif
640 
641 /****************************************************************************
642  * 6510 section
643  ****************************************************************************/
644 #if (HAS_M6510)
m6510_reset(void * param)645 void m6510_reset (void *param)
646 {
647 	m6502_reset(param);
648 	m6502.subtype = SUBTYPE_6510;
649 	m6502.insn = insn6510;
650 }
m6510_exit(void)651 void m6510_exit  (void) { m6502_exit(); }
m6510_execute(int cycles)652 int  m6510_execute(int cycles) { return m6502_execute(cycles); }
m6510_get_context(void * dst)653 unsigned m6510_get_context (void *dst) { return m6502_get_context(dst); }
m6510_set_context(void * src)654 void m6510_set_context (void *src) { m6502_set_context(src); }
m6510_get_pc(void)655 unsigned m6510_get_pc (void) { return m6502_get_pc(); }
m6510_set_pc(unsigned val)656 void m6510_set_pc (unsigned val) { m6502_set_pc(val); }
m6510_get_sp(void)657 unsigned m6510_get_sp (void) { return m6502_get_sp(); }
m6510_set_sp(unsigned val)658 void m6510_set_sp (unsigned val) { m6502_set_sp(val); }
m6510_get_reg(int regnum)659 unsigned m6510_get_reg (int regnum) { return m6502_get_reg(regnum); }
m6510_set_reg(int regnum,unsigned val)660 void m6510_set_reg (int regnum, unsigned val) { m6502_set_reg(regnum,val); }
m6510_set_nmi_line(int state)661 void m6510_set_nmi_line(int state) { m6502_set_nmi_line(state); }
m6510_set_irq_line(int irqline,int state)662 void m6510_set_irq_line(int irqline, int state) { m6502_set_irq_line(irqline,state); }
m6510_set_irq_callback(int (* callback)(int irqline))663 void m6510_set_irq_callback(int (*callback)(int irqline)) { m6502_set_irq_callback(callback); }
m6510_state_save(void * file)664 void m6510_state_save(void *file) { m6502_state_save(file); }
m6510_state_load(void * file)665 void m6510_state_load(void *file) { m6502_state_load(file); }
m6510_info(void * context,int regnum)666 const char *m6510_info(void *context, int regnum)
667 {
668 	switch( regnum )
669 	{
670 		case CPU_INFO_NAME: return "M6510";
671 		case CPU_INFO_VERSION: return "1.2";
672 	}
673 	return m6502_info(context,regnum);
674 }
675 
m6510_dasm(char * buffer,unsigned pc)676 unsigned m6510_dasm(char *buffer, unsigned pc)
677 {
678 	sprintf( buffer, "$%02X", cpu_readop(pc) );
679 	return 1;
680 }
681 #endif
682 
683 #if (HAS_M6510T)
m6510t_info(void * context,int regnum)684 const char *m6510t_info(void *context, int regnum)
685 {
686 	switch( regnum )
687 	{
688 		case CPU_INFO_NAME: return "M6510T";
689 	}
690 	return m6510_info(context,regnum);
691 }
692 #endif
693 
694 #if (HAS_M7501)
m7501_info(void * context,int regnum)695 const char *m7501_info(void *context, int regnum)
696 {
697 	switch( regnum )
698 	{
699 		case CPU_INFO_NAME: return "M7501";
700 	}
701 	return m6510_info(context,regnum);
702 }
703 #endif
704 
705 #if (HAS_M8502)
m8502_info(void * context,int regnum)706 const char *m8502_info(void *context, int regnum)
707 {
708 	switch( regnum )
709 	{
710 		case CPU_INFO_NAME: return "M8502";
711 	}
712 	return m6510_info(context,regnum);
713 }
714 #endif
715