1 // 680x0 (Sixty Eight K) Interface
2 // Interface picked from pfba (https://github.com/Cpasjuste/pfba)
3 #include "burnint.h"
4 #include "m68000_intf.h"
5 #include "m68000_debug.h"
6
7 #define EMU_C68K
8
9 #ifdef EMU_M68K
10 INT32 nSekM68KContextSize[SEK_MAX];
11 INT8* SekM68KContext[SEK_MAX];
12 #endif
13
14 #ifdef EMU_C68K
15 #include "Cyclone.h"
16 struct Cyclone c68k[SEK_MAX];
17 static bool bCycloneInited = false;
18 #endif
19
20 INT32 nSekCount = -1; // Number of allocated 68000s
21 struct SekExt *SekExt[SEK_MAX] = { NULL, }, *pSekExt = NULL;
22
23 INT32 nSekActive = -1; // The cpu which is currently being emulated
24 INT32 nSekCyclesTotal, nSekCyclesScanline, nSekCyclesSegment, nSekCyclesDone, nSekCyclesToDo;
25
26 INT32 nSekCPUType[SEK_MAX], nSekCycles[SEK_MAX], nSekIRQPending[SEK_MAX];
27
28 cpu_core_config SekConfig =
29 {
30 SekOpen,
31 SekClose,
32 SekCheatRead,
33 SekWriteByteROM,
34 SekGetActive,
35 SekTotalCycles,
36 SekNewFrame,
37 SekRun,
38 SekRunEnd,
39 SekReset,
40 0x1000000,
41 0
42 };
43
44 // ----------------------------------------------------------------------------
45 // Default memory access handlers
46
DefReadByte(UINT32)47 UINT8 __fastcall DefReadByte(UINT32) { return 0; }
DefWriteByte(UINT32,UINT8)48 void __fastcall DefWriteByte(UINT32, UINT8) { }
49
50 #define DEFWORDHANDLERS(i) \
51 UINT16 __fastcall DefReadWord##i(UINT32 a) { SEK_DEF_READ_WORD(i, a) } \
52 void __fastcall DefWriteWord##i(UINT32 a, UINT16 d) { SEK_DEF_WRITE_WORD(i, a ,d) }
53 #define DEFLONGHANDLERS(i) \
54 UINT32 __fastcall DefReadLong##i(UINT32 a) { SEK_DEF_READ_LONG(i, a) } \
55 void __fastcall DefWriteLong##i(UINT32 a, UINT32 d) { SEK_DEF_WRITE_LONG(i, a , d) }
56
57 DEFWORDHANDLERS(0)
58 DEFLONGHANDLERS(0)
59
60 #if SEK_MAXHANDLER >= 2
61 DEFWORDHANDLERS(1)
62 DEFLONGHANDLERS(1)
63 #endif
64
65 #if SEK_MAXHANDLER >= 3
66 DEFWORDHANDLERS(2)
67 DEFLONGHANDLERS(2)
68 #endif
69
70 #if SEK_MAXHANDLER >= 4
71 DEFWORDHANDLERS(3)
72 DEFLONGHANDLERS(3)
73 #endif
74
75 #if SEK_MAXHANDLER >= 5
76 DEFWORDHANDLERS(4)
77 DEFLONGHANDLERS(4)
78 #endif
79
80 #if SEK_MAXHANDLER >= 6
81 DEFWORDHANDLERS(5)
82 DEFLONGHANDLERS(5)
83 #endif
84
85 #if SEK_MAXHANDLER >= 7
86 DEFWORDHANDLERS(6)
87 DEFLONGHANDLERS(6)
88 #endif
89
90 #if SEK_MAXHANDLER >= 8
91 DEFWORDHANDLERS(7)
92 DEFLONGHANDLERS(7)
93 #endif
94
95 #if SEK_MAXHANDLER >= 9
96 DEFWORDHANDLERS(8)
97 DEFLONGHANDLERS(8)
98 #endif
99
100 #if SEK_MAXHANDLER >= 10
101 DEFWORDHANDLERS(9)
102 DEFLONGHANDLERS(9)
103 #endif
104
105 // ----------------------------------------------------------------------------
106 // Memory access functions
107
108 // Mapped Memory lookup ( for read)
109 #define FIND_R(x) pSekExt->MemMap[ x >> SEK_SHIFT]
110 // Mapped Memory lookup (+ SEK_WADD for write)
111 #define FIND_W(x) pSekExt->MemMap[(x >> SEK_SHIFT) + SEK_WADD]
112 // Mapped Memory lookup (+ SEK_WADD * 2 for fetch)
113 #define FIND_F(x) pSekExt->MemMap[(x >> SEK_SHIFT) + SEK_WADD * 2]
114
115 // Normal memory access functions
116 extern "C" {
m68k_read8(unsigned int a)117 unsigned int m68k_read8(unsigned int a)
118 {
119 UINT8* pr;
120
121 a &= 0xFFFFFF;
122
123 // bprintf(PRINT_NORMAL, _T("read8 0x%08X\n"), a);
124
125 pr = FIND_R(a);
126 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
127 a ^= 1;
128 return pr[a & SEK_PAGEM];
129 }
130 return pSekExt->ReadByte[(uintptr_t)pr](a);
131 }
132
m68k_fetch8(unsigned int a)133 unsigned int m68k_fetch8(unsigned int a)
134 {
135 UINT8* pr;
136
137 a &= 0xFFFFFF;
138
139 // bprintf(PRINT_NORMAL, _T("fetch8 0x%08X\n"), a);
140
141 pr = FIND_F(a);
142 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
143 a ^= 1;
144 return pr[a & SEK_PAGEM];
145 }
146 return pSekExt->ReadByte[(uintptr_t)pr](a);
147 }
148
m68k_write8(unsigned int a,unsigned char d)149 void m68k_write8(unsigned int a, unsigned char d)
150 {
151 UINT8* pr;
152
153 a &= 0xFFFFFF;
154
155 // bprintf(PRINT_NORMAL, _T("write8 0x%08X\n"), a);
156
157 pr = FIND_W(a);
158 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
159 a ^= 1;
160 pr[a & SEK_PAGEM] = (UINT8)d;
161 return;
162 }
163 pSekExt->WriteByte[(uintptr_t)pr](a, d);
164 }
165
WriteByteROM(UINT32 a,UINT8 d)166 inline static void WriteByteROM(UINT32 a, UINT8 d)
167 {
168 UINT8* pr;
169
170 a &= 0xFFFFFF;
171
172 pr = FIND_R(a);
173 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
174 a ^= 1;
175 pr[a & SEK_PAGEM] = (UINT8)d;
176 return;
177 }
178 pSekExt->WriteByte[(uintptr_t)pr](a, d);
179 }
180
m68k_read16(unsigned int a)181 unsigned int m68k_read16(unsigned int a)
182 {
183 UINT8* pr;
184
185 a &= 0xFFFFFF;
186
187 // bprintf(PRINT_NORMAL, _T("read16 0x%08X\n"), a);
188
189 pr = FIND_R(a);
190 if ((uintptr_t)pr >= SEK_MAXHANDLER)
191 {
192 if (a & 1)
193 {
194 return BURN_ENDIAN_SWAP_INT16((M68KReadByte(a + 0) * 256) + M68KReadByte(a + 1));
195 }
196 else
197 {
198 return BURN_ENDIAN_SWAP_INT16(*((UINT16*)(pr + (a & SEK_PAGEM))));
199 }
200 }
201 return pSekExt->ReadWord[(uintptr_t)pr](a);
202 }
203
m68k_fetch16(unsigned int a)204 unsigned int m68k_fetch16(unsigned int a)
205 {
206 UINT8* pr;
207
208 a &= 0xFFFFFF;
209
210 // bprintf(PRINT_NORMAL, _T("fetch16 0x%08X\n"), a);
211
212 pr = FIND_F(a);
213 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
214 return BURN_ENDIAN_SWAP_INT16(*((UINT16*)(pr + (a & SEK_PAGEM))));
215 }
216 return pSekExt->ReadWord[(uintptr_t)pr](a);
217 }
218
m68k_write16(unsigned int a,unsigned short d)219 void m68k_write16(unsigned int a, unsigned short d)
220 {
221 UINT8* pr;
222
223 a &= 0xFFFFFF;
224
225 // bprintf(PRINT_NORMAL, _T("write16 0x%08X\n"), a);
226
227 pr = FIND_W(a);
228 if ((uintptr_t)pr >= SEK_MAXHANDLER)
229 {
230 if (a & 1)
231 {
232 // bprintf(PRINT_NORMAL, _T("write16 0x%08X\n"), a);
233 d = BURN_ENDIAN_SWAP_INT16(d);
234 M68KWriteByte(a + 0, d / 0x100);
235 M68KWriteByte(a + 1, d);
236 return;
237 }
238 else
239 {
240 *((UINT16 *) (pr + (a & SEK_PAGEM))) = (UINT16) BURN_ENDIAN_SWAP_INT16(d);
241 return;
242 }
243 }
244 pSekExt->WriteWord[(uintptr_t)pr](a, d);
245 }
246
WriteWordROM(UINT32 a,UINT16 d)247 inline static void WriteWordROM(UINT32 a, UINT16 d)
248 {
249 UINT8* pr;
250
251 a &= 0xFFFFFF;
252
253 pr = FIND_R(a);
254 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
255 *((UINT16*)(pr + (a & SEK_PAGEM))) = (UINT16)d;
256 return;
257 }
258 pSekExt->WriteWord[(uintptr_t)pr](a, d);
259 }
260
m68k_read32(unsigned int a)261 unsigned int m68k_read32(unsigned int a)
262 {
263 UINT8* pr;
264
265 a &= 0xFFFFFF;
266
267 // bprintf(PRINT_NORMAL, _T("read32 0x%08X\n"), a);
268
269 pr = FIND_R(a);
270 if ((uintptr_t)pr >= SEK_MAXHANDLER)
271 {
272 UINT32 r = 0;
273
274 if (a & 1)
275 {
276 r = M68KReadByte((a + 0)) * 0x1000000;
277 r += M68KReadByte((a + 1)) * 0x10000;
278 r += M68KReadByte((a + 2)) * 0x100;
279 r += M68KReadByte((a + 3));
280
281 return BURN_ENDIAN_SWAP_INT32(r);
282 }
283 else
284 {
285 r = *((UINT32*)(pr + (a & SEK_PAGEM)));
286 r = (r >> 16) | (r << 16);
287
288 return BURN_ENDIAN_SWAP_INT32(r);
289 }
290 }
291 return pSekExt->ReadLong[(uintptr_t)pr](a);
292 }
293
m68k_fetch32(unsigned int a)294 unsigned int m68k_fetch32(unsigned int a)
295 {
296 UINT8* pr;
297
298 a &= 0xFFFFFF;
299
300 // bprintf(PRINT_NORMAL, _T("fetch32 0x%08X\n"), a);
301
302 pr = FIND_F(a);
303 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
304 UINT32 r = *((UINT32*)(pr + (a & SEK_PAGEM)));
305 r = (r >> 16) | (r << 16);
306 return BURN_ENDIAN_SWAP_INT32(r);
307 }
308 return pSekExt->ReadLong[(uintptr_t)pr](a);
309 }
310
m68k_write32(unsigned int a,unsigned int d)311 void m68k_write32(unsigned int a, unsigned int d)
312 {
313 UINT8* pr;
314
315 a &= 0xFFFFFF;
316
317 // bprintf(PRINT_NORMAL, _T("write32 0x%08X\n"), a);
318
319 pr = FIND_W(a);
320 if ((uintptr_t)pr >= SEK_MAXHANDLER)
321 {
322 if (a & 1)
323 {
324 // bprintf(PRINT_NORMAL, _T("write32 0x%08X 0x%8.8x\n"), a,d);
325
326 d = BURN_ENDIAN_SWAP_INT32(d);
327
328 M68KWriteByte((a + 0), d / 0x1000000);
329 M68KWriteByte((a + 1), d / 0x10000);
330 M68KWriteByte((a + 2), d / 0x100);
331 M68KWriteByte((a + 3), d);
332
333 return;
334 }
335 else
336 {
337 d = (d >> 16) | (d << 16);
338 *((UINT32*)(pr + (a & SEK_PAGEM))) = BURN_ENDIAN_SWAP_INT32(d);
339
340 return;
341 }
342 }
343 pSekExt->WriteLong[(uintptr_t)pr](a, d);
344 }
345
WriteLongROM(UINT32 a,UINT32 d)346 inline static void WriteLongROM(UINT32 a, UINT32 d)
347 {
348 UINT8* pr;
349
350 a &= 0xFFFFFF;
351
352 pr = FIND_R(a);
353 if ((uintptr_t)pr >= SEK_MAXHANDLER) {
354 d = (d >> 16) | (d << 16);
355 *((UINT32*)(pr + (a & SEK_PAGEM))) = d;
356 return;
357 }
358 pSekExt->WriteLong[(uintptr_t)pr](a, d);
359 }
360 }
361
362 #ifdef EMU_M68K
363 extern "C" {
M68KReadByte(UINT32 a)364 UINT32 __fastcall M68KReadByte(UINT32 a) { return (UINT32)m68k_read8(a); }
M68KReadWord(UINT32 a)365 UINT32 __fastcall M68KReadWord(UINT32 a) { return (UINT32)m68k_read16(a); }
M68KReadLong(UINT32 a)366 UINT32 __fastcall M68KReadLong(UINT32 a) { return m68k_read32(a); }
367
M68KFetchByte(UINT32 a)368 UINT32 __fastcall M68KFetchByte(UINT32 a) { return (UINT32)m68k_fetch8(a); }
M68KFetchWord(UINT32 a)369 UINT32 __fastcall M68KFetchWord(UINT32 a) { return (UINT32)m68k_fetch16(a); }
M68KFetchLong(UINT32 a)370 UINT32 __fastcall M68KFetchLong(UINT32 a) { return m68k_fetch32(a); }
371
M68KWriteByte(UINT32 a,UINT32 d)372 void __fastcall M68KWriteByte(UINT32 a, UINT32 d) { m68k_write8(a, d); }
M68KWriteWord(UINT32 a,UINT32 d)373 void __fastcall M68KWriteWord(UINT32 a, UINT32 d) { m68k_write16(a, d); }
M68KWriteLong(UINT32 a,UINT32 d)374 void __fastcall M68KWriteLong(UINT32 a, UINT32 d) { m68k_write32(a, d); }
375 }
376 #endif
377
378 // ----------------------------------------------------------------------------
379 // Memory accesses (non-emu specific)
380
SekReadByte(UINT32 a)381 UINT32 SekReadByte(UINT32 a) { return (UINT32)m68k_read8(a); }
SekReadWord(UINT32 a)382 UINT32 SekReadWord(UINT32 a) { return (UINT32)m68k_read16(a); }
SekReadLong(UINT32 a)383 UINT32 SekReadLong(UINT32 a) { return m68k_read32(a); }
384
SekFetchByte(UINT32 a)385 UINT32 SekFetchByte(UINT32 a) { return (UINT32)m68k_fetch8(a); }
SekFetchWord(UINT32 a)386 UINT32 SekFetchWord(UINT32 a) { return (UINT32)m68k_fetch16(a); }
SekFetchLong(UINT32 a)387 UINT32 SekFetchLong(UINT32 a) { return m68k_fetch32(a); }
388
SekWriteByte(UINT32 a,UINT8 d)389 void SekWriteByte(UINT32 a, UINT8 d) { m68k_write8(a, d); }
SekWriteWord(UINT32 a,UINT16 d)390 void SekWriteWord(UINT32 a, UINT16 d) { m68k_write16(a, d); }
SekWriteLong(UINT32 a,UINT32 d)391 void SekWriteLong(UINT32 a, UINT32 d) { m68k_write32(a, d); }
392
SekWriteByteROM(UINT32 a,UINT8 d)393 void SekWriteByteROM(UINT32 a, UINT8 d) { WriteByteROM(a, d); }
SekWriteWordROM(UINT32 a,UINT16 d)394 void SekWriteWordROM(UINT32 a, UINT16 d) { WriteWordROM(a, d); }
SekWriteLongROM(UINT32 a,UINT32 d)395 void SekWriteLongROM(UINT32 a, UINT32 d) { WriteLongROM(a, d); }
396
397 // ----------------------------------------------------------------------------
398 // Callbacks for C68K
399
400 #ifdef EMU_C68K
m68k_checkpc(UINT32 pc)401 extern "C" unsigned int m68k_checkpc(UINT32 pc)
402 {
403 pc -= c68k[nSekActive].membase; // Get real pc
404 pc &= 0xffffff;
405
406 c68k[nSekActive].membase = (uintptr_t)FIND_F(pc) - (pc & ~SEK_PAGEM);
407
408 return c68k[nSekActive].membase + pc;
409 }
410
C68KIRQAcknowledge(INT32 nIRQ)411 extern "C" INT32 C68KIRQAcknowledge(INT32 nIRQ)
412 {
413 if (nSekIRQPending[nSekActive] & SEK_IRQSTATUS_AUTO) {
414 c68k[nSekActive].irq = 0;
415 nSekIRQPending[nSekActive] = 0;
416 }
417
418 if (pSekExt->IrqCallback) {
419 return pSekExt->IrqCallback(nIRQ);
420 }
421
422 return CYCLONE_INT_ACK_AUTOVECTOR;
423 }
424
C68KResetCallback()425 extern "C" void C68KResetCallback()
426 {
427 if (pSekExt->ResetCallback) {
428 pSekExt->ResetCallback();
429 }
430 }
431
C68KUnrecognizedCallback()432 extern "C" int C68KUnrecognizedCallback()
433 {
434 #if defined (FBA_DEBUG)
435 bprintf(PRINT_NORMAL, _T("UnrecognizedCallback();\n"));
436 #endif
437 return 0;
438 }
439
C68KRTECallback()440 extern "C" void C68KRTECallback()
441 {
442 if (pSekExt->RTECallback) {
443 pSekExt->RTECallback();
444 }
445 }
446
C68KcmpildCallback(UINT32 val,INT32 reg)447 extern "C" void C68KcmpildCallback(UINT32 val, INT32 reg)
448 {
449 if (pSekExt->CmpCallback) {
450 pSekExt->CmpCallback(val, reg);
451 }
452 }
453
C68KTASCallback()454 extern "C" INT32 C68KTASCallback()
455 {
456 if (pSekExt->TASCallback) {
457 return pSekExt->TASCallback();
458 }
459
460 return 0; // disabled by default
461 }
462 #endif
463
464 // ----------------------------------------------------------------------------
465 // Callbacks for Musashi
466
467 #ifdef EMU_M68K
M68KIRQAcknowledge(INT32 nIRQ)468 extern "C" INT32 M68KIRQAcknowledge(INT32 nIRQ)
469 {
470 if (nSekIRQPending[nSekActive] & SEK_IRQSTATUS_AUTO) {
471 m68k_set_irq(0);
472 nSekIRQPending[nSekActive] = 0;
473 }
474
475 if (pSekExt->IrqCallback) {
476 return pSekExt->IrqCallback(nIRQ);
477 }
478
479 return M68K_INT_ACK_AUTOVECTOR;
480 }
481
M68KResetCallback()482 extern "C" void M68KResetCallback()
483 {
484 if (pSekExt->ResetCallback) {
485 pSekExt->ResetCallback();
486 }
487 }
488
M68KRTECallback()489 extern "C" void M68KRTECallback()
490 {
491 if (pSekExt->RTECallback) {
492 pSekExt->RTECallback();
493 }
494 }
495
M68KcmpildCallback(UINT32 val,INT32 reg)496 extern "C" void M68KcmpildCallback(UINT32 val, INT32 reg)
497 {
498 if (pSekExt->CmpCallback) {
499 pSekExt->CmpCallback(val, reg);
500 }
501 }
502
M68KTASCallback()503 extern "C" INT32 M68KTASCallback()
504 {
505 if (pSekExt->TASCallback) {
506 return pSekExt->TASCallback();
507 }
508
509 return 1; // enable by default
510 }
511 #endif
512
513 // ----------------------------------------------------------------------------
514 // Initialisation/exit/reset
515
516 #ifdef EMU_C68K
SekInitCPUC68K(INT32 nCount,INT32 nCPUType)517 static INT32 SekInitCPUC68K(INT32 nCount, INT32 nCPUType)
518 {
519 #if defined (FBA_DEBUG)
520 bprintf(PRINT_NORMAL, _T("EMU_C68K: SekInitCPUC68K(%i, %x)\n"), nCount, nCPUType);
521 #endif
522 if (nCPUType != 0x68000) {
523 return 1;
524 }
525
526 nSekCPUType[nCount] = nCPUType;
527
528 if (!bCycloneInited) {
529 #if defined (FBA_DEBUG)
530 bprintf(PRINT_NORMAL, _T("EMU_C68K: CycloneInit\n"));
531 #endif
532 CycloneInit();
533 #if defined (FBA_DEBUG)
534 bprintf(PRINT_NORMAL, _T("EMU_C68K: CycloneInit OK\n"));
535 #endif
536 bCycloneInited = true;
537 }
538 memset(&c68k[nCount], 0, sizeof(Cyclone));
539 c68k[nCount].checkpc = m68k_checkpc;
540 c68k[nCount].IrqCallback = C68KIRQAcknowledge;
541 c68k[nCount].ResetCallback = C68KResetCallback;
542 c68k[nCount].UnrecognizedCallback = C68KUnrecognizedCallback;
543
544 return 0;
545 }
546 #endif
547
548 #ifdef EMU_M68K
SekInitCPUM68K(INT32 nCount,INT32 nCPUType)549 static INT32 SekInitCPUM68K(INT32 nCount, INT32 nCPUType)
550 {
551 #if defined (FBA_DEBUG)
552 bprintf(PRINT_NORMAL, _T("EMU_M68K: SekInitCPUM68K(%i, %x)\n"), nCount, nCPUType);
553 #endif
554 nSekCPUType[nCount] = nCPUType;
555
556 switch (nCPUType) {
557 case 0x68000:
558 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
559 break;
560 case 0x68010:
561 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
562 break;
563 case 0x68EC020:
564 m68k_set_cpu_type(M68K_CPU_TYPE_68EC020);
565 break;
566 default:
567 return 1;
568 }
569
570 nSekM68KContextSize[nCount] = m68k_context_size();
571 SekM68KContext[nCount] = (INT8*)malloc(nSekM68KContextSize[nCount]);
572 if (SekM68KContext[nCount] == NULL) {
573 return 1;
574 }
575 memset(SekM68KContext[nCount], 0, nSekM68KContextSize[nCount]);
576 m68k_get_context(SekM68KContext[nCount]);
577
578 return 0;
579 }
580 #endif
581
SekNewFrame()582 void SekNewFrame()
583 {
584 #if defined FBA_DEBUG
585 if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, _T("SekNewFrame called without init\n"));
586 #endif
587
588 for (INT32 i = 0; i <= nSekCount; i++) {
589 nSekCycles[i] = 0;
590 }
591
592 nSekCyclesTotal = 0;
593 }
594
SekSetCyclesScanline(INT32 nCycles)595 void SekSetCyclesScanline(INT32 nCycles)
596 {
597 #if defined FBA_DEBUG
598 if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, _T("SekSetCyclesScanline called without init\n"));
599 if (nSekActive == -1) bprintf(PRINT_ERROR, _T("SekSetCyclesScanline called when no CPU open\n"));
600 #endif
601
602 nSekCyclesScanline = nCycles;
603 }
604
SekCheatRead(UINT32 a)605 UINT8 SekCheatRead(UINT32 a)
606 {
607 return SekReadByte(a);
608 }
609
SekInit(INT32 nCount,INT32 nCPUType)610 INT32 SekInit(INT32 nCount, INT32 nCPUType)
611 {
612 DebugCPU_SekInitted = 1;
613
614 struct SekExt* ps = NULL;
615
616 /*#if !defined BUILD_A68K
617 bBurnUseASMCPUEmulation = false;
618 #endif*/
619
620 if (nSekActive >= 0) {
621 SekClose();
622 nSekActive = -1;
623 }
624
625 if (nCount > nSekCount) {
626 nSekCount = nCount;
627 }
628
629 // Allocate cpu extenal data (memory map etc)
630 SekExt[nCount] = (struct SekExt*)malloc(sizeof(struct SekExt));
631 if (SekExt[nCount] == NULL) {
632 SekExit();
633 return 1;
634 }
635 memset(SekExt[nCount], 0, sizeof(struct SekExt));
636
637 // Put in default memory handlers
638 ps = SekExt[nCount];
639
640 for (INT32 j = 0; j < SEK_MAXHANDLER; j++) {
641 ps->ReadByte[j] = DefReadByte;
642 ps->WriteByte[j] = DefWriteByte;
643 }
644
645 ps->ReadWord[0] = DefReadWord0;
646 ps->WriteWord[0] = DefWriteWord0;
647 ps->ReadLong[0] = DefReadLong0;
648 ps->WriteLong[0] = DefWriteLong0;
649
650 #if SEK_MAXHANDLER >= 2
651 ps->ReadWord[1] = DefReadWord1;
652 ps->WriteWord[1] = DefWriteWord1;
653 ps->ReadLong[1] = DefReadLong1;
654 ps->WriteLong[1] = DefWriteLong1;
655 #endif
656
657 #if SEK_MAXHANDLER >= 3
658 ps->ReadWord[2] = DefReadWord2;
659 ps->WriteWord[2] = DefWriteWord2;
660 ps->ReadLong[2] = DefReadLong2;
661 ps->WriteLong[2] = DefWriteLong2;
662 #endif
663
664 #if SEK_MAXHANDLER >= 4
665 ps->ReadWord[3] = DefReadWord3;
666 ps->WriteWord[3] = DefWriteWord3;
667 ps->ReadLong[3] = DefReadLong3;
668 ps->WriteLong[3] = DefWriteLong3;
669 #endif
670
671 #if SEK_MAXHANDLER >= 5
672 ps->ReadWord[4] = DefReadWord4;
673 ps->WriteWord[4] = DefWriteWord4;
674 ps->ReadLong[4] = DefReadLong4;
675 ps->WriteLong[4] = DefWriteLong4;
676 #endif
677
678 #if SEK_MAXHANDLER >= 6
679 ps->ReadWord[5] = DefReadWord5;
680 ps->WriteWord[5] = DefWriteWord5;
681 ps->ReadLong[5] = DefReadLong5;
682 ps->WriteLong[5] = DefWriteLong5;
683 #endif
684
685 #if SEK_MAXHANDLER >= 7
686 ps->ReadWord[6] = DefReadWord6;
687 ps->WriteWord[6] = DefWriteWord6;
688 ps->ReadLong[6] = DefReadLong6;
689 ps->WriteLong[6] = DefWriteLong6;
690 #endif
691
692 #if SEK_MAXHANDLER >= 8
693 ps->ReadWord[7] = DefReadWord7;
694 ps->WriteWord[7] = DefWriteWord7;
695 ps->ReadLong[7] = DefReadLong7;
696 ps->WriteLong[7] = DefWriteLong7;
697 #endif
698
699 #if SEK_MAXHANDLER >= 9
700 ps->ReadWord[8] = DefReadWord8;
701 ps->WriteWord[8] = DefWriteWord8;
702 ps->ReadLong[8] = DefReadLong8;
703 ps->WriteLong[8] = DefWriteLong8;
704 #endif
705
706 #if SEK_MAXHANDLER >= 10
707 ps->ReadWord[9] = DefReadWord9;
708 ps->WriteWord[9] = DefWriteWord9;
709 ps->ReadLong[9] = DefReadLong9;
710 ps->WriteLong[9] = DefWriteLong9;
711 #endif
712
713 #if SEK_MAXHANDLER >= 11
714 for (int j = 10; j < SEK_MAXHANDLER; j++) {
715 ps->ReadWord[j] = DefReadWord0;
716 ps->WriteWord[j] = DefWriteWord0;
717 ps->ReadLong[j] = DefReadLong0;
718 ps->WriteLong[j] = DefWriteLong0;
719 }
720 #endif
721
722 // Map the normal memory handlers
723 SekDbgDisableBreakpoints();
724
725 #ifdef EMU_C68K
726 if ((nSekCpuCore == SEK_CORE_C68K) && nCPUType == 0x68000) {
727 if (SekInitCPUC68K(nCount, nCPUType)) {
728 SekExit();
729 return 1;
730 }
731 } else {
732 #endif
733
734 #ifdef EMU_M68K
735 m68k_init();
736 if (SekInitCPUM68K(nCount, nCPUType)) {
737 SekExit();
738 return 1;
739 }
740 #endif
741
742 #ifdef EMU_C68K
743 }
744 #endif
745
746 nSekCycles[nCount] = 0;
747 nSekIRQPending[nCount] = 0;
748
749 nSekCyclesTotal = 0;
750 nSekCyclesScanline = 0;
751
752 CpuCheatRegister(nCount, &SekConfig);
753
754 return 0;
755 }
756
757 #ifdef EMU_M68K
SekCPUExitM68K(INT32 i)758 static void SekCPUExitM68K(INT32 i)
759 {
760 if(SekM68KContext[i]) {
761 free(SekM68KContext[i]);
762 SekM68KContext[i] = NULL;
763 }
764 }
765 #endif
766
SekExit()767 INT32 SekExit()
768 {
769 // Deallocate cpu extenal data (memory map etc)
770 for (INT32 i = 0; i <= nSekCount; i++) {
771
772 #ifdef EMU_M68K
773 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[i] == 0x68000) {
774 #if defined (FBA_DEBUG)
775 bprintf(PRINT_NORMAL, _T("EMU_C68K: SekExit\n"));
776 #endif
777 } else {
778 #if defined (FBA_DEBUG)
779 bprintf(PRINT_NORMAL, _T("EMU_M68K: SekExit\n"));
780 #endif
781 SekCPUExitM68K(i);
782 }
783 #endif
784
785 // Deallocate other context data
786 if (SekExt[i]) {
787 free(SekExt[i]);
788 SekExt[i] = NULL;
789 }
790 }
791
792 pSekExt = NULL;
793
794 nSekActive = -1;
795 nSekCount = -1;
796
797 DebugCPU_SekInitted = 0;
798
799 return 0;
800 }
801
SekReset()802 void SekReset()
803 {
804 #ifdef EMU_C68K
805 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
806 #if defined (FBA_DEBUG)
807 bprintf(PRINT_NORMAL, _T("EMU_C68K: SekReset\n"));
808 #endif
809 memset(&c68k[nSekActive], 0, 22 * 4); // clear all regs
810 c68k[nSekActive].state_flags = 0;
811 c68k[nSekActive].srh = 0x27; // Supervisor mode
812 c68k[nSekActive].a[7] = m68k_fetch32(0); // Stack Pointer
813 c68k[nSekActive].membase = 0;
814 c68k[nSekActive].pc = c68k[nSekActive].checkpc(m68k_fetch32(4));
815 } else {
816 #endif
817
818 #ifdef EMU_M68K
819 #if defined (FBA_DEBUG)
820 bprintf(PRINT_NORMAL, _T("EMU_M68K: SekReset\n"));
821 #endif
822 m68k_pulse_reset();
823 #endif
824
825 #ifdef EMU_C68K
826 }
827 #endif
828
829 }
830
831 // ----------------------------------------------------------------------------
832 // Control the active CPU
833
834 // Open a CPU
SekOpen(const INT32 i)835 void SekOpen(const INT32 i)
836 {
837 if (i != nSekActive) {
838 nSekActive = i;
839
840 pSekExt = SekExt[nSekActive]; // Point to cpu context
841
842 #ifdef EMU_C68K
843 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
844 //...
845 } else {
846 #endif
847
848 #ifdef EMU_M68K
849 m68k_set_context(SekM68KContext[nSekActive]);
850 #endif
851
852 #ifdef EMU_C68K
853 }
854 #endif
855
856 nSekCyclesTotal = nSekCycles[nSekActive];
857 }
858 }
859
860 // Close the active cpu
SekClose()861 void SekClose()
862 {
863 #ifdef EMU_C68K
864 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
865 //...
866 } else {
867 #endif
868
869 #ifdef EMU_M68K
870 m68k_get_context(SekM68KContext[nSekActive]);
871 #endif
872
873 #ifdef EMU_C68K
874 }
875 #endif
876
877 nSekCycles[nSekActive] = nSekCyclesTotal;
878
879 nSekActive = -1;
880 }
881
882 // Get the current CPU
SekGetActive()883 INT32 SekGetActive()
884 {
885 return nSekActive;
886 }
887
888 // For Megadrive - check if the vdp controlport should set IRQ
SekShouldInterrupt(void)889 INT32 SekShouldInterrupt(void)
890 {
891 if(nSekCpuCore == SEK_CORE_M68K) {
892 return m68k_check_shouldinterrupt();
893 } else {
894 return 0;
895 }
896 }
897
898 // Set the status of an IRQ line on the active CPU
SekSetIRQLine(const INT32 line,const INT32 nstatus)899 void SekSetIRQLine(const INT32 line, const INT32 nstatus)
900 {
901 INT32 status = nstatus << 12; // needed for compatibility
902
903 if (status) {
904 nSekIRQPending[nSekActive] = line | status;
905
906 #ifdef EMU_C68K
907 //printf("EMU_C68K: SekSetIRQLine\n");
908 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
909 nSekCyclesTotal += (nSekCyclesToDo - nSekCyclesDone) - c68k[nSekActive].cycles;
910 nSekCyclesDone += (nSekCyclesToDo - nSekCyclesDone) - c68k[nSekActive].cycles;
911
912 c68k[nSekActive].irq = line;
913 c68k[nSekActive].cycles = nSekCyclesToDo = -1;
914 } else {
915 #endif
916
917 #ifdef EMU_M68K
918 //printf("EMU_M68K: SekSetIRQLine\n");
919 m68k_set_irq(line);
920 #endif
921
922 #ifdef EMU_C68K
923 }
924 #endif
925
926 return;
927 }
928
929 nSekIRQPending[nSekActive] = 0;
930
931 #ifdef EMU_C68K
932 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
933 c68k[nSekActive].irq = 0;
934 } else {
935 #endif
936
937 #ifdef EMU_M68K
938 m68k_set_irq(0);
939 #endif
940
941 #ifdef EMU_C68K
942 }
943 #endif
944
945 }
946
947 // Adjust the active CPU's timeslice
SekRunAdjust(const INT32 nCycles)948 void SekRunAdjust(const INT32 nCycles)
949 {
950 #ifndef EMU_C68K
951 INT32 count = m68k_ICount;
952 #else
953 INT32 count = nSekCpuCore ==
954 SEK_CORE_C68K && nSekCPUType[nSekActive] == 0x68000 ?
955 c68k[nSekActive].cycles : m68k_ICount;
956 #endif
957 if (nCycles < 0 && count < -nCycles) {
958 SekRunEnd();
959 return;
960 }
961
962 #ifdef EMU_C68K
963 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
964 //printf("EMU_C68K: SekRunAdjust\n");
965 c68k[nSekActive].cycles += nCycles;
966 nSekCyclesToDo += nCycles;
967 nSekCyclesSegment += nCycles;
968 } else {
969 #endif
970
971 #ifdef EMU_M68K
972 //printf("EMU_M68K: SekRunAdjust\n");
973 nSekCyclesToDo += nCycles;
974 m68k_modify_timeslice(nCycles);
975 #endif
976
977 #ifdef EMU_C68K
978 }
979 #endif
980
981 }
982
983 // End the active CPU's timeslice
SekRunEnd()984 void SekRunEnd()
985 {
986 #ifdef EMU_C68K
987 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
988 nSekCyclesTotal += (nSekCyclesToDo - nSekCyclesDone) - c68k[nSekActive].cycles;
989 nSekCyclesDone += (nSekCyclesToDo - nSekCyclesDone) - c68k[nSekActive].cycles;
990 nSekCyclesSegment = nSekCyclesDone;
991 c68k[nSekActive].cycles = nSekCyclesToDo = -1;
992 } else {
993 #endif
994
995 #ifdef EMU_M68K
996 m68k_end_timeslice();
997 #endif
998
999 #ifdef EMU_C68K
1000 }
1001 #endif
1002
1003 }
1004
1005 // Run the active CPU
SekRun(const INT32 nCycles)1006 INT32 SekRun(const INT32 nCycles)
1007 {
1008 #ifdef EMU_C68K
1009 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
1010 //printf("EMU_C68K: SekRun\n");
1011 nSekCyclesDone = 0;
1012 nSekCyclesSegment = nCycles;
1013 do {
1014 c68k[nSekActive].cycles = nSekCyclesToDo = nSekCyclesSegment - nSekCyclesDone;
1015
1016 if (c68k[nSekActive].irq == 0x80) { // Cpu is in stopped state till interrupt
1017 nSekCyclesDone = nSekCyclesSegment;
1018 nSekCyclesTotal += nSekCyclesSegment;
1019 } else {
1020 CycloneRun(&c68k[nSekActive]);
1021 nSekCyclesDone += nSekCyclesToDo - c68k[nSekActive].cycles;
1022 nSekCyclesTotal += nSekCyclesToDo - c68k[nSekActive].cycles;
1023 }
1024 } while (nSekCyclesDone < nSekCyclesSegment);
1025
1026 nSekCyclesSegment = nSekCyclesDone;
1027 nSekCyclesToDo = c68k[nSekActive].cycles = -1;
1028 nSekCyclesDone = 0;
1029
1030 return nSekCyclesSegment; // Return the number of cycles actually done
1031 } else {
1032 #endif
1033
1034 #ifdef EMU_M68K
1035 //printf("EMU_M68K: SekRun\n");
1036 nSekCyclesToDo = nCycles;
1037 nSekCyclesSegment = m68k_execute(nCycles);
1038 nSekCyclesTotal += nSekCyclesSegment;
1039 nSekCyclesToDo = m68k_ICount = -1;
1040 return nSekCyclesSegment;
1041 #endif
1042
1043 #ifdef EMU_C68K
1044 }
1045 #endif
1046
1047 }
1048
1049 // ----------------------------------------------------------------------------
1050 // Breakpoint support
1051
SekDbgDisableBreakpoints()1052 void SekDbgDisableBreakpoints()
1053 {
1054 #if defined FBA_DEBUG && defined EMU_M68K
1055 m68k_set_instr_hook_callback(NULL);
1056
1057 M68KReadByteDebug = M68KReadByte;
1058 M68KReadWordDebug = M68KReadWord;
1059 M68KReadLongDebug = M68KReadLong;
1060
1061 M68KWriteByteDebug = M68KWriteByte;
1062 M68KWriteWordDebug = M68KWriteWord;
1063 M68KWriteLongDebug = M68KWriteLong;
1064 #endif
1065
1066 #ifdef EMU_A68K
1067 a68k_memory_intf = a68k_inter_normal;
1068 #endif
1069
1070 //mame_debug = 0;
1071 }
1072
1073 // ----------------------------------------------------------------------------
1074 // Memory map setup
1075
1076 // Note - each page is 1 << SEK_BITS.
SekMapMemory(UINT8 * pMemory,UINT32 nStart,UINT32 nEnd,INT32 nType)1077 INT32 SekMapMemory(UINT8* pMemory, UINT32 nStart, UINT32 nEnd, INT32 nType)
1078 {
1079 UINT8* Ptr = pMemory - nStart;
1080 UINT8** pMemMap = pSekExt->MemMap + (nStart >> SEK_SHIFT);
1081
1082 // Special case for ROM banks
1083 if (nType == MAP_ROM) {
1084 for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) {
1085 pMemMap[0] = Ptr + i;
1086 pMemMap[SEK_WADD * 2] = Ptr + i;
1087 }
1088
1089 return 0;
1090 }
1091
1092 for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) {
1093
1094 if (nType & MAP_READ) { // Read
1095 pMemMap[0] = Ptr + i;
1096 }
1097 if (nType & MAP_WRITE) { // Write
1098 pMemMap[SEK_WADD] = Ptr + i;
1099 }
1100 if (nType & MAP_FETCH) { // Fetch
1101 pMemMap[SEK_WADD * 2] = Ptr + i;
1102 }
1103 }
1104
1105 return 0;
1106 }
1107
SekMapHandler(uintptr_t nHandler,UINT32 nStart,UINT32 nEnd,INT32 nType)1108 INT32 SekMapHandler(uintptr_t nHandler, UINT32 nStart, UINT32 nEnd, INT32 nType)
1109 {
1110 UINT8** pMemMap = pSekExt->MemMap + (nStart >> SEK_SHIFT);
1111
1112 // Add to memory map
1113 for (UINT32 i = (nStart & ~SEK_PAGEM); i <= nEnd; i += SEK_PAGE_SIZE, pMemMap++) {
1114
1115 if (nType & MAP_READ) { // Read
1116 pMemMap[0] = (UINT8*)nHandler;
1117 }
1118 if (nType & MAP_WRITE) { // Write
1119 pMemMap[SEK_WADD] = (UINT8*)nHandler;
1120 }
1121 if (nType & MAP_FETCH) { // Fetch
1122 pMemMap[SEK_WADD * 2] = (UINT8*)nHandler;
1123 }
1124 }
1125
1126 return 0;
1127 }
1128
1129 // Set callbacks
SekSetResetCallback(pSekResetCallback pCallback)1130 INT32 SekSetResetCallback(pSekResetCallback pCallback)
1131 {
1132 pSekExt->ResetCallback = pCallback;
1133
1134 return 0;
1135 }
1136
SekSetRTECallback(pSekRTECallback pCallback)1137 INT32 SekSetRTECallback(pSekRTECallback pCallback)
1138 {
1139 pSekExt->RTECallback = pCallback;
1140
1141 return 0;
1142 }
1143
SekSetIrqCallback(pSekIrqCallback pCallback)1144 INT32 SekSetIrqCallback(pSekIrqCallback pCallback)
1145 {
1146 pSekExt->IrqCallback = pCallback;
1147
1148 return 0;
1149 }
1150
SekSetCmpCallback(pSekCmpCallback pCallback)1151 INT32 SekSetCmpCallback(pSekCmpCallback pCallback)
1152 {
1153 pSekExt->CmpCallback = pCallback;
1154
1155 return 0;
1156 }
1157
SekSetTASCallback(pSekTASCallback pCallback)1158 INT32 SekSetTASCallback(pSekTASCallback pCallback)
1159 {
1160 pSekExt->TASCallback = pCallback;
1161
1162 return 0;
1163 }
1164
1165 // Set handlers
SekSetReadByteHandler(INT32 i,pSekReadByteHandler pHandler)1166 INT32 SekSetReadByteHandler(INT32 i, pSekReadByteHandler pHandler)
1167 {
1168 if (i >= SEK_MAXHANDLER) {
1169 return 1;
1170 }
1171
1172 pSekExt->ReadByte[i] = pHandler;
1173
1174 return 0;
1175 }
1176
SekSetWriteByteHandler(INT32 i,pSekWriteByteHandler pHandler)1177 INT32 SekSetWriteByteHandler(INT32 i, pSekWriteByteHandler pHandler)
1178 {
1179 if (i >= SEK_MAXHANDLER) {
1180 return 1;
1181 }
1182
1183 pSekExt->WriteByte[i] = pHandler;
1184
1185 return 0;
1186 }
1187
SekSetReadWordHandler(INT32 i,pSekReadWordHandler pHandler)1188 INT32 SekSetReadWordHandler(INT32 i, pSekReadWordHandler pHandler)
1189 {
1190 if (i >= SEK_MAXHANDLER) {
1191 return 1;
1192 }
1193
1194 pSekExt->ReadWord[i] = pHandler;
1195
1196 return 0;
1197 }
1198
SekSetWriteWordHandler(INT32 i,pSekWriteWordHandler pHandler)1199 INT32 SekSetWriteWordHandler(INT32 i, pSekWriteWordHandler pHandler)
1200 {
1201 if (i >= SEK_MAXHANDLER) {
1202 return 1;
1203 }
1204
1205 pSekExt->WriteWord[i] = pHandler;
1206
1207 return 0;
1208 }
1209
SekSetReadLongHandler(INT32 i,pSekReadLongHandler pHandler)1210 INT32 SekSetReadLongHandler(INT32 i, pSekReadLongHandler pHandler)
1211 {
1212 if (i >= SEK_MAXHANDLER) {
1213 return 1;
1214 }
1215
1216 pSekExt->ReadLong[i] = pHandler;
1217
1218 return 0;
1219 }
1220
SekSetWriteLongHandler(INT32 i,pSekWriteLongHandler pHandler)1221 INT32 SekSetWriteLongHandler(INT32 i, pSekWriteLongHandler pHandler)
1222 {
1223 if (i >= SEK_MAXHANDLER) {
1224 return 1;
1225 }
1226
1227 pSekExt->WriteLong[i] = pHandler;
1228
1229 return 0;
1230 }
1231
1232 // ----------------------------------------------------------------------------
1233 // Query register values
1234
1235 #ifdef EMU_C68K
SekGetPC(INT32 n)1236 UINT32 SekGetPC(INT32 n)
1237 #else
1238 UINT32 SekGetPC(INT32)
1239 #endif
1240 {
1241 #ifdef EMU_C68K
1242 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[nSekActive] == 0x68000) {
1243 return c68k[nSekActive].pc-c68k[nSekActive].membase;
1244 } else {
1245 #endif
1246
1247 #ifdef EMU_M68K
1248 return m68k_get_reg(NULL, M68K_REG_PC);
1249 #else
1250 return 0;
1251 #endif
1252
1253 #ifdef EMU_C68K
1254 }
1255 #endif
1256
1257 }
1258
SekDbgGetCPUType()1259 INT32 SekDbgGetCPUType()
1260 {
1261 switch (nSekCPUType[nSekActive]) {
1262 case 0:
1263 case 0x68000:
1264 return M68K_CPU_TYPE_68000;
1265 case 0x68010:
1266 return M68K_CPU_TYPE_68010;
1267 case 0x68EC020:
1268 return M68K_CPU_TYPE_68EC020;
1269 }
1270
1271 return 0;
1272 }
1273
SekDbgGetPendingIRQ()1274 INT32 SekDbgGetPendingIRQ()
1275 {
1276 return nSekIRQPending[nSekActive] & 7;
1277 }
1278
SekDbgGetRegister(SekRegister nRegister)1279 UINT32 SekDbgGetRegister(SekRegister nRegister)
1280 {
1281 return 0;
1282 }
1283
SekDbgSetRegister(SekRegister nRegister,UINT32 nValue)1284 bool SekDbgSetRegister(SekRegister nRegister, UINT32 nValue)
1285 {
1286 return false;
1287 }
1288
1289 // ----------------------------------------------------------------------------
1290 // Savestate support
1291
1292 UINT8 cyclone_buffer[128];
1293
SekScan(INT32 nAction)1294 INT32 SekScan(INT32 nAction)
1295 {
1296 // Scan the 68000 states
1297 struct BurnArea ba;
1298
1299 if ((nAction & ACB_DRIVER_DATA) == 0) {
1300 return 1;
1301 }
1302
1303 memset(&ba, 0, sizeof(ba));
1304
1305 nSekActive = -1;
1306
1307 for (INT32 i = 0; i <= nSekCount; i++) {
1308
1309 char szName[] = "MC68000 #n";
1310 szName[9] = '0' + i;
1311
1312 SCAN_VAR(nSekCPUType[i]);
1313 SCAN_VAR(nSekIRQPending[i]);
1314 SCAN_VAR(nSekCycles[i]);
1315
1316 #ifdef EMU_C68K
1317 if ((nSekCpuCore == SEK_CORE_C68K) && nSekCPUType[i] == 0x68000) {
1318
1319 ba.nLen = 128;
1320 ba.szName = szName;
1321
1322 if (nAction & ACB_READ) { // save
1323 memset(cyclone_buffer, 0, 128);
1324 CyclonePack(&c68k[i], cyclone_buffer);
1325 ba.Data = &cyclone_buffer;
1326 BurnAcb(&ba);
1327 } else if (nAction & ACB_WRITE) { // load
1328 memset(cyclone_buffer, 0, 128);
1329 ba.Data = &cyclone_buffer;
1330 BurnAcb(&ba);
1331 int sekActive = nSekActive; // CycloneUnpack needs m68k_checkpc which needs nSekActive set to current cpu
1332 nSekActive = i; // CycloneUnpack needs m68k_checkpc which needs nSekActive set to current cpu
1333 CycloneUnpack(&c68k[i], cyclone_buffer);
1334 nSekActive = sekActive;
1335 }
1336 } else {
1337 #endif
1338 #ifdef EMU_M68K
1339 if (nSekCPUType[i] != 0) {
1340 ba.Data = SekM68KContext[i];
1341 // for savestate portability: preserve our cpu's pointers, they are set up in DrvInit() and can be specific to different systems.
1342 // Therefore we scan the cpu context structure up until right before the pointers
1343 ba.nLen = m68k_context_size_no_pointers();
1344 ba.szName = szName;
1345 BurnAcb(&ba);
1346 }
1347 #endif
1348 #ifdef EMU_C68K
1349 }
1350 #endif
1351 }
1352
1353 return 0;
1354 }
1355