1 #include "burnint.h"
2 #include "m6502_intf.h"
3 #include <stddef.h>
4 
5 #define MAX_CPU		8
6 
7 INT32 nM6502Count = 0;
8 static INT32 nActiveCPU = 0;
9 
10 static M6502Ext *m6502CPUContext[MAX_CPU] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
11 static M6502Ext *pCurrentCPU;
12 static INT32 nM6502CyclesDone[MAX_CPU];
13 INT32 nM6502CyclesTotal;
14 
15 cpu_core_config M6502Config =
16 {
17 	M6502Open,
18 	M6502Close,
19 	M6502CheatRead,
20 	M6502WriteRom,
21 	M6502GetActive,
22 	M6502TotalCycles,
23 	M6502NewFrame,
24 	M6502Run,
25 	M6502RunEnd,
26 	M6502Reset,
27 	0x10000,
28 	0
29 };
30 
M6502ReadPortDummyHandler(UINT16)31 static UINT8 M6502ReadPortDummyHandler(UINT16)
32 {
33 	return 0;
34 }
35 
M6502WritePortDummyHandler(UINT16,UINT8)36 static void M6502WritePortDummyHandler(UINT16, UINT8)
37 {
38 }
39 
M6502ReadByteDummyHandler(UINT16)40 static UINT8 M6502ReadByteDummyHandler(UINT16)
41 {
42 	return 0;
43 }
44 
M6502WriteByteDummyHandler(UINT16,UINT8)45 static void M6502WriteByteDummyHandler(UINT16, UINT8)
46 {
47 }
48 
M6502ReadOpDummyHandler(UINT16)49 static UINT8 M6502ReadOpDummyHandler(UINT16)
50 {
51 	return 0;
52 }
53 
M6502ReadOpArgDummyHandler(UINT16)54 static UINT8 M6502ReadOpArgDummyHandler(UINT16)
55 {
56 	return 0;
57 }
58 
M6502Reset()59 void M6502Reset()
60 {
61 #if defined FBA_DEBUG
62 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Reset called without init\n"));
63 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502Reset called with no CPU open\n"));
64 #endif
65 
66 	pCurrentCPU->reset();
67 }
68 
M6502NewFrame()69 void M6502NewFrame()
70 {
71 #if defined FBA_DEBUG
72 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502NewFrame called without init\n"));
73 #endif
74 
75 	for (INT32 i = 0; i < nM6502Count; i++) {
76 		nM6502CyclesDone[i] = 0;
77 	}
78 	nM6502CyclesTotal = 0;
79 }
80 
M6502CheatRead(UINT32 a)81 UINT8 M6502CheatRead(UINT32 a)
82 {
83 	return M6502ReadByte(a);
84 }
85 
decocpu7Decode(UINT16,UINT8 op)86 static UINT8 decocpu7Decode(UINT16 /*address*/,UINT8 op)
87 {
88 	return (op & 0x13) | ((op & 0x80) >> 5) | ((op & 0x64) << 1) | ((op & 0x08) << 2);
89 }
90 
M6502Init(INT32 cpu,INT32 type)91 INT32 M6502Init(INT32 cpu, INT32 type)
92 {
93 	DebugCPU_M6502Initted = 1;
94 
95 	nM6502Count++;
96 	nActiveCPU = -1;
97 
98 	m6502CPUContext[cpu] = (M6502Ext*)BurnMalloc(sizeof(M6502Ext));
99 
100 	pCurrentCPU = m6502CPUContext[cpu];
101 
102 	memset(pCurrentCPU, 0, sizeof(M6502Ext));
103 
104 	for (INT32 i = 0; i < 0x100; i++) {
105 		pCurrentCPU->opcode_reorder[i] = i;
106 	}
107 
108 	switch (type)
109 	{
110 		case TYPE_M6502:
111 		case TYPE_M6504:
112 			pCurrentCPU->execute = m6502_execute;
113 			pCurrentCPU->reset = m6502_reset;
114 			pCurrentCPU->init = m6502_init;
115 			pCurrentCPU->set_irq_line = m6502_set_irq_line;
116 		break;
117 
118 		case TYPE_DECOCPU7:
119 			pCurrentCPU->execute = decocpu7_execute;
120 			pCurrentCPU->reset = m6502_reset;
121 			pCurrentCPU->init = m6502_init;
122 			pCurrentCPU->set_irq_line = m6502_set_irq_line;
123 		break;
124 
125 		case TYPE_DECO222:
126 		case TYPE_DECOC10707:
127 		{
128 			pCurrentCPU->execute = m6502_execute;
129 			pCurrentCPU->reset = m6502_reset;
130 			pCurrentCPU->init = m6502_init;
131 			pCurrentCPU->set_irq_line = m6502_set_irq_line;
132 
133 			for (INT32 i = 0; i < 0x100; i++) {
134 				pCurrentCPU->opcode_reorder[i] = (i & 0x9f) | ((i >> 1) & 0x20) | ((i & 0x20) << 1);
135 			}
136 		}
137 		break;
138 
139 		case TYPE_M65C02:
140 			pCurrentCPU->execute = m65c02_execute;
141 			pCurrentCPU->reset = m65c02_reset;
142 			pCurrentCPU->init = m65c02_init;
143 			pCurrentCPU->set_irq_line = m65c02_set_irq_line;
144 		break;
145 
146 		case TYPE_DECO16:
147 			pCurrentCPU->execute = deco16_execute;
148 			pCurrentCPU->reset = deco16_reset;
149 			pCurrentCPU->init = deco16_init;
150 			pCurrentCPU->set_irq_line = deco16_set_irq_line;
151 		break;
152 
153 		case TYPE_N2A03:
154 			pCurrentCPU->execute = m6502_execute;
155 			pCurrentCPU->reset = m6502_reset;
156 			pCurrentCPU->init = n2a03_init;		// different
157 			pCurrentCPU->set_irq_line = m6502_set_irq_line;
158 		break;
159 
160 		case TYPE_M65SC02:
161 			pCurrentCPU->execute = m65c02_execute;
162 			pCurrentCPU->reset = m65c02_reset;
163 			pCurrentCPU->init = m65sc02_init;	// different
164 			pCurrentCPU->set_irq_line = m65c02_set_irq_line;
165 		break;
166 
167 		case TYPE_M6510:
168 		case TYPE_M6510T:
169 		case TYPE_M7501:
170 		case TYPE_M8502:
171 			pCurrentCPU->execute = m6502_execute;
172 			pCurrentCPU->reset = m6510_reset;	// different
173 			pCurrentCPU->init = m6510_init;		// different
174 			pCurrentCPU->set_irq_line = m6502_set_irq_line;
175 		break;
176 	}
177 
178 	pCurrentCPU->ReadPort = M6502ReadPortDummyHandler;
179 	pCurrentCPU->WritePort = M6502WritePortDummyHandler;
180 	pCurrentCPU->ReadByte = M6502ReadByteDummyHandler;
181 	pCurrentCPU->WriteByte = M6502WriteByteDummyHandler;
182 	pCurrentCPU->ReadOp = M6502ReadOpDummyHandler;
183 	pCurrentCPU->ReadOpArg = M6502ReadOpArgDummyHandler;
184 
185 	nM6502CyclesDone[cpu] = 0;
186 
187 	pCurrentCPU->AddressMask = (1 << 16) - 1; // cpu range
188 
189 	for (INT32 j = 0; j < (0x0100 * 3); j++) {
190 		pCurrentCPU->pMemMap[j] = NULL;
191 	}
192 
193 	nM6502CyclesTotal = 0;
194 
195 	M6502Open(cpu);
196 	pCurrentCPU->init();
197 	M6502Close();
198 
199 	if (type == TYPE_DECOCPU7) {
200 		M6502Open(cpu);
201 		DecoCpu7SetDecode(decocpu7Decode);
202 		M6502Close();
203 	}
204 
205 	CpuCheatRegister(cpu, &M6502Config);
206 
207 	return 0;
208 }
209 
M6502Exit()210 void M6502Exit()
211 {
212 #if defined FBA_DEBUG
213 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Exit called without init\n"));
214 #endif
215 
216 	if (!DebugCPU_M6502Initted) return;
217 
218 	for (INT32 i = 0; i < MAX_CPU; i++) {
219 		if (m6502CPUContext[i]) {
220 			BurnFree(m6502CPUContext[i]);
221 			m6502CPUContext[i] = NULL;
222 		}
223 	}
224 
225 	m6502_core_exit();
226 
227 	nM6502Count = 0;
228 
229 	DebugCPU_M6502Initted = 0;
230 }
231 
M6502SetOpcodeDecode(UINT8 * table)232 void M6502SetOpcodeDecode(UINT8 *table)
233 {
234 #if defined FBA_DEBUG
235 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetOpcodeDecode called without init\n"));
236 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetOpcodeDecode called with no CPU open\n"));
237 #endif
238 	memcpy (pCurrentCPU->opcode_reorder, table, 0x100);
239 }
240 
M6502Open(INT32 num)241 void M6502Open(INT32 num)
242 {
243 #if defined FBA_DEBUG
244 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Open called without init\n"));
245 	if (num >= nM6502Count) bprintf(PRINT_ERROR, _T("M6502Open called with invalid index %x\n"), num);
246 	if (nActiveCPU != -1) bprintf(PRINT_ERROR, _T("M6502Open called with CPU already open with index %x\n"), num);
247 #endif
248 
249 	nActiveCPU = num;
250 
251 	pCurrentCPU = m6502CPUContext[num];
252 
253 	m6502_set_context(&pCurrentCPU->reg);
254 
255 	nM6502CyclesTotal = nM6502CyclesDone[nActiveCPU];
256 }
257 
M6502Close()258 void M6502Close()
259 {
260 #if defined FBA_DEBUG
261 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Close called without init\n"));
262 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502Close called with no CPU open\n"));
263 #endif
264 
265 	m6502_get_context(&pCurrentCPU->reg);
266 
267 	nM6502CyclesDone[nActiveCPU] = nM6502CyclesTotal;
268 
269 	pCurrentCPU = NULL; // cause problems!
270 
271 	nActiveCPU = -1;
272 }
273 
M6502GetActive()274 INT32 M6502GetActive()
275 {
276 #if defined FBA_DEBUG
277 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502GetActive called without init\n"));
278 	//if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502GetActive called with no CPU open\n"));
279 #endif
280 
281 	return nActiveCPU;
282 }
283 
M6502Idle(INT32 nCycles)284 INT32 M6502Idle(INT32 nCycles)
285 {
286 #if defined FBA_DEBUG
287 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Idle called without init\n"));
288 #endif
289 
290 	nM6502CyclesTotal += nCycles;
291 
292 	return nCycles;
293 }
294 
M6502ReleaseSlice()295 void M6502ReleaseSlice()
296 {
297 #if defined FBA_DEBUG
298 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502ReleaseSlice called without init\n"));
299 #endif
300 
301 	m6502_releaseslice();
302 }
303 
M6502SetIRQLine(INT32 vector,INT32 status)304 void M6502SetIRQLine(INT32 vector, INT32 status)
305 {
306 #if defined FBA_DEBUG
307 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetIRQLineLine called without init\n"));
308 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetIRQLineLine called with no CPU open\n"));
309 #endif
310 
311 	if (status == CPU_IRQSTATUS_NONE) {
312 		pCurrentCPU->set_irq_line(vector, 0);
313 		return;
314 	}
315 
316 	if (status == CPU_IRQSTATUS_ACK) {
317 		pCurrentCPU->set_irq_line(vector, 1);
318 		return;
319 	}
320 
321 	if (status == CPU_IRQSTATUS_AUTO) {
322 		if (vector == CPU_IRQLINE_NMI /* 0x20 */) {
323 			pCurrentCPU->set_irq_line(vector, 1);
324 			pCurrentCPU->set_irq_line(vector, 0);
325 			return;
326 		} else {
327 			pCurrentCPU->set_irq_line(vector, 1);
328 			pCurrentCPU->execute(0);
329 			pCurrentCPU->set_irq_line(vector, 0);
330 			pCurrentCPU->execute(0);
331 			return;
332 		}
333 	}
334 
335 	if (status == CPU_IRQSTATUS_HOLD) {
336 		m6502_set_irq_hold();
337 		pCurrentCPU->set_irq_line(vector, 1);
338 		return;
339 	}
340 }
341 
M6502Run(INT32 cycles)342 INT32 M6502Run(INT32 cycles)
343 {
344 #if defined FBA_DEBUG
345 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Run called without init\n"));
346 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502Run called with no CPU open\n"));
347 #endif
348 
349 	cycles = pCurrentCPU->execute(cycles);
350 
351 	nM6502CyclesTotal += cycles;
352 
353 	return cycles;
354 }
355 
M6502RunEnd()356 void M6502RunEnd()
357 {
358 #if defined FBA_DEBUG
359 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502RunEnd called without init\n"));
360 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502RunEnd called with no CPU open\n"));
361 #endif
362 }
363 
M6502MapMemory(UINT8 * pMemory,UINT16 nStart,UINT16 nEnd,INT32 nType)364 INT32 M6502MapMemory(UINT8* pMemory, UINT16 nStart, UINT16 nEnd, INT32 nType)
365 {
366 #if defined FBA_DEBUG
367 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502MapMemory called without init\n"));
368 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502MapMemory called with no CPU open\n"));
369 #endif
370 
371 	UINT8 cStart = (nStart >> 8);
372 	UINT8 **pMemMap = pCurrentCPU->pMemMap;
373 
374 	for (UINT16 i = cStart; i <= (nEnd >> 8); i++) {
375 		if (nType & MAP_READ)	{
376 			pMemMap[0     + i] = (pMemory == NULL) ? NULL : (pMemory + ((i - cStart) << 8));
377 		}
378 		if (nType & MAP_WRITE) {
379 			pMemMap[0x100 + i] = (pMemory == NULL) ? NULL : (pMemory + ((i - cStart) << 8));
380 		}
381 		if (nType & MAP_FETCH) {
382 			pMemMap[0x200 + i] = (pMemory == NULL) ? NULL : (pMemory + ((i - cStart) << 8));
383 		}
384 	}
385 	return 0;
386 }
387 
M6502SetAddressMask(UINT16 RangeMask)388 void M6502SetAddressMask(UINT16 RangeMask)
389 {
390 #if defined FBA_DEBUG
391 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetAddressMask called without init\n"));
392 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetAddressMask called with no CPU open\n"));
393 	if ((RangeMask & 0xff) != 0xff) bprintf (PRINT_ERROR, _T("M6502SetAddressMask with likely bad mask value (%4.4x)!\n"), RangeMask);
394 #endif
395 
396 	pCurrentCPU->AddressMask = RangeMask;
397 
398 }
399 
M6502SetReadPortHandler(UINT8 (* pHandler)(UINT16))400 void M6502SetReadPortHandler(UINT8 (*pHandler)(UINT16))
401 {
402 #if defined FBA_DEBUG
403 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetReadPortHandler called without init\n"));
404 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetReadPortHandler called with no CPU open\n"));
405 #endif
406 	pCurrentCPU->ReadPort = pHandler;
407 }
408 
M6502SetWritePortHandler(void (* pHandler)(UINT16,UINT8))409 void M6502SetWritePortHandler(void (*pHandler)(UINT16, UINT8))
410 {
411 #if defined FBA_DEBUG
412 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetWritePortHandler called without init\n"));
413 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetWritePortHandler called with no CPU open\n"));
414 #endif
415 
416 	pCurrentCPU->WritePort = pHandler;
417 }
418 
M6502SetReadHandler(UINT8 (* pHandler)(UINT16))419 void M6502SetReadHandler(UINT8 (*pHandler)(UINT16))
420 {
421 #if defined FBA_DEBUG
422 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetReadHandler called without init\n"));
423 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetReadHandler called with no CPU open\n"));
424 #endif
425 
426 	pCurrentCPU->ReadByte = pHandler;
427 }
428 
M6502SetWriteHandler(void (* pHandler)(UINT16,UINT8))429 void M6502SetWriteHandler(void (*pHandler)(UINT16, UINT8))
430 {
431 #if defined FBA_DEBUG
432 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetWriteHandler called without init\n"));
433 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetWriteHandler called with no CPU open\n"));
434 #endif
435 
436 	pCurrentCPU->WriteByte = pHandler;
437 }
438 
M6502SetReadOpHandler(UINT8 (* pHandler)(UINT16))439 void M6502SetReadOpHandler(UINT8 (*pHandler)(UINT16))
440 {
441 #if defined FBA_DEBUG
442 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetReadOpHandler called without init\n"));
443 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetReadOpHandler called with no CPU open\n"));
444 #endif
445 
446 	pCurrentCPU->ReadOp = pHandler;
447 }
448 
M6502SetReadOpArgHandler(UINT8 (* pHandler)(UINT16))449 void M6502SetReadOpArgHandler(UINT8 (*pHandler)(UINT16))
450 {
451 #if defined FBA_DEBUG
452 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502SetReadOpArgHandler called without init\n"));
453 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502SetReadOpArgHandler called with no CPU open\n"));
454 #endif
455 
456 	pCurrentCPU->ReadOpArg = pHandler;
457 }
458 
M6502ReadPort(UINT16 Address)459 UINT8 M6502ReadPort(UINT16 Address)
460 {
461 	// check handler
462 	if (pCurrentCPU->ReadPort != NULL) {
463 		return pCurrentCPU->ReadPort(Address);
464 	}
465 
466 	return 0;
467 }
468 
M6502WritePort(UINT16 Address,UINT8 Data)469 void M6502WritePort(UINT16 Address, UINT8 Data)
470 {
471 	// check handler
472 	if (pCurrentCPU->WritePort != NULL) {
473 		pCurrentCPU->WritePort(Address, Data);
474 		return;
475 	}
476 }
477 
M6502ReadByte(UINT16 Address)478 UINT8 M6502ReadByte(UINT16 Address)
479 {
480 	Address &= pCurrentCPU->AddressMask;
481 
482 	// check mem map
483 	UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)];
484 	if (pr != NULL) {
485 		return pr[Address & 0xff];
486 	}
487 
488 	// check handler
489 	if (pCurrentCPU->ReadByte != NULL) {
490 		return pCurrentCPU->ReadByte(Address);
491 	}
492 
493 	return 0;
494 }
495 
M6502WriteByte(UINT16 Address,UINT8 Data)496 void M6502WriteByte(UINT16 Address, UINT8 Data)
497 {
498 	Address &= pCurrentCPU->AddressMask;
499 
500 	// check mem map
501 	UINT8 * pr = pCurrentCPU->pMemMap[0x100 | (Address >> 8)];
502 	if (pr != NULL) {
503 		pr[Address & 0xff] = Data;
504 		return;
505 	}
506 
507 	// check handler
508 	if (pCurrentCPU->WriteByte != NULL) {
509 		pCurrentCPU->WriteByte(Address, Data);
510 		return;
511 	}
512 }
513 
M6502ReadOp(UINT16 Address)514 UINT8 M6502ReadOp(UINT16 Address)
515 {
516 	Address &= pCurrentCPU->AddressMask;
517 
518 	// check mem map
519 	UINT8 * pr = pCurrentCPU->pMemMap[0x200 | (Address >> 8)];
520 	if (pr != NULL) {
521 		return pCurrentCPU->opcode_reorder[pr[Address & 0xff]];
522 	}
523 
524 	// check handler
525 	if (pCurrentCPU->ReadOp != NULL) {
526 		return pCurrentCPU->opcode_reorder[pCurrentCPU->ReadOp(Address)];
527 	}
528 
529 	return 0;
530 }
531 
M6502ReadOpArg(UINT16 Address)532 UINT8 M6502ReadOpArg(UINT16 Address)
533 {
534 	Address &= pCurrentCPU->AddressMask;
535 
536 	// check mem map
537 	UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)];
538 	if (pr != NULL) {
539 		return pr[Address & 0xff];
540 	}
541 
542 	// check handler
543 	if (pCurrentCPU->ReadOpArg != NULL) {
544 		return pCurrentCPU->ReadOpArg(Address);
545 	}
546 
547 	return 0;
548 }
549 
M6502WriteRom(UINT32 Address,UINT8 Data)550 void M6502WriteRom(UINT32 Address, UINT8 Data)
551 {
552 	Address &= pCurrentCPU->AddressMask;
553 
554 #if defined FBA_DEBUG
555 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502WriteRom called without init\n"));
556 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502WriteRom called with no CPU open\n"));
557 #endif
558 
559 	Address &= 0xffff;
560 
561 	UINT8 * pr = pCurrentCPU->pMemMap[0x000 | (Address >> 8)];
562 	UINT8 * pw = pCurrentCPU->pMemMap[0x100 | (Address >> 8)];
563 	UINT8 * pf = pCurrentCPU->pMemMap[0x200 | (Address >> 8)];
564 
565 	if (pr != NULL) {
566 		pr[Address & 0xff] = Data;
567 	}
568 
569 	if (pw != NULL) {
570 		pw[Address & 0xff] = Data;
571 	}
572 
573 	if (pf != NULL) {
574 		pf[Address & 0xff] = Data;
575 	}
576 
577 	// check handler
578 	if (pCurrentCPU->WriteByte != NULL) {
579 		pCurrentCPU->WriteByte(Address, Data);
580 		return;
581 	}
582 }
583 
M6502GetPC(INT32)584 UINT32 M6502GetPC(INT32)
585 {
586 #if defined FBA_DEBUG
587 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502GetPC called without init\n"));
588 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502GetPC called with no CPU open\n"));
589 #endif
590 
591 	return m6502_get_pc();
592 }
593 
M6502GetPrevPC(INT32)594 UINT32 M6502GetPrevPC(INT32)
595 {
596 #if defined FBA_DEBUG
597 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502GetPrevPC called without init\n"));
598 	if (nActiveCPU == -1) bprintf(PRINT_ERROR, _T("M6502GetPrevPC called with no CPU open\n"));
599 #endif
600 
601 	return m6502_get_prev_pc();
602 }
603 
M6502Scan(INT32 nAction)604 INT32 M6502Scan(INT32 nAction)
605 {
606 #if defined FBA_DEBUG
607 	if (!DebugCPU_M6502Initted) bprintf(PRINT_ERROR, _T("M6502Scan called without init\n"));
608 #endif
609 
610 	struct BurnArea ba;
611 
612 	if ((nAction & ACB_DRIVER_DATA) == 0) {
613 		return 1;
614 	}
615 
616 	for (INT32 i = 0; i < nM6502Count; i++) {
617 
618 		M6502Ext *ptr = m6502CPUContext[i];
619 
620 		char szName[] = "M6502 #n";
621 		szName[7] = '0' + i;
622 
623 		ba.Data = &ptr->reg;
624 		ba.nLen = STRUCT_SIZE_HELPER(m6502_Regs, port);
625 		ba.szName = szName;
626 		BurnAcb(&ba);
627 
628 		// necessary?
629 		SCAN_VAR(ptr->nCyclesTotal);
630 		SCAN_VAR(ptr->nCyclesSegment);
631 		SCAN_VAR(ptr->nCyclesLeft);
632 		SCAN_VAR(nM6502CyclesDone);
633 	}
634 
635 	return 0;
636 }
637