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