1 // 68000 (Sixty Eight K) Interface - header file
2 #include <stdint.h>
3 #ifndef FASTCALL
4  #undef __fastcall
5  #define __fastcall
6 #endif
7 
8 #if defined BUILD_A68K
9  #define EMU_A68K								// Use A68K Assembler 68000 emulator
10 #endif
11 
12 #define EMU_M68K								// Use Musashi 68000 emulator
13 
14 #define SEK_MAX	(5)								// Maximum number of CPUs supported
15 
16 #if defined EMU_M68K
17  #include "m68k/m68k.h"
18 #endif
19 
20 // Number of bits used for each page in the fast memory map
21 #define SEK_BITS		(10)					// 10 = 0x0400 page size
22 #define SEK_PAGE_COUNT  (1 << (24 - SEK_BITS))	// Number of pages
23 #define SEK_SHIFT		(SEK_BITS)				// Shift value = page bits
24 #define SEK_PAGE_SIZE	(1 << SEK_BITS)			// Page size
25 #define SEK_PAGEM		(SEK_PAGE_SIZE - 1)
26 #define SEK_WADD		(SEK_PAGE_COUNT)		// Value to add for write section = Number of pages
27 #define SEK_MASK		(SEK_WADD - 1)
28 #define SEK_MAXHANDLER	(10)						// Max. number of handlers for memory access
29 
30 #if SEK_MAXHANDLER < 1
31  #error At least one set of handlers for memory access must be used.
32 #endif
33 
34 #ifdef EMU_A68K
35  extern "C" void __cdecl M68000_RUN();
36  extern "C" void __cdecl M68000_RESET();
37 #endif
38 
39 #ifdef EMU_A68K
40  // The format of the data in a68k.asm (at the _M68000_regs location)
41  struct A68KContext {
42 	UINT32 d[8], a[8];
43 	UINT32 isp, srh, ccr, xc, pc, irq, sr;
44 	INT32 (*IrqCallback) (INT32 nIrq);
45 	UINT32 ppc;
46 	INT32 (*ResetCallback)();
47 	INT32 (*RTECallback)();
48 	INT32 (*CmpCallback)(UINT32 val, INT32 reg);
49 	UINT32 sfc, dfc, usp, vbr;
50 	UINT32 nAsmBank, nCpuVersion;
51  };
52  extern "C" struct A68KContext M68000_regs;
53  extern     struct A68KContext* SekRegs[SEK_MAX];
54 
55  extern "C" UINT8* OP_ROM;
56  extern "C" UINT8* OP_RAM;
57 
58  void __fastcall AsekChangePc(UINT32 pc);
59 #endif
60 
61 #ifdef EMU_M68K
62  extern "C" INT32 nSekM68KContextSize[SEK_MAX];
63  extern "C" INT8* SekM68KContext[SEK_MAX];
64  extern "C" INT32 m68k_ICount;
65 #endif
66 
67 typedef UINT8 (__fastcall *pSekReadByteHandler)(UINT32 a);
68 typedef void (__fastcall *pSekWriteByteHandler)(UINT32 a, UINT8 d);
69 typedef UINT16 (__fastcall *pSekReadWordHandler)(UINT32 a);
70 typedef void (__fastcall *pSekWriteWordHandler)(UINT32 a, UINT16 d);
71 typedef UINT32 (__fastcall *pSekReadLongHandler)(UINT32 a);
72 typedef void (__fastcall *pSekWriteLongHandler)(UINT32 a, UINT32 d);
73 
74 typedef INT32 (__fastcall *pSekResetCallback)();
75 typedef INT32 (__fastcall *pSekRTECallback)();
76 typedef INT32 (__fastcall *pSekIrqCallback)(INT32 irq);
77 typedef INT32 (__fastcall *pSekCmpCallback)(UINT32 val, INT32 reg);
78 typedef INT32 (__fastcall *pSekTASCallback)();
79 
80 extern INT32 nSekCycles[SEK_MAX], nSekCPUType[SEK_MAX];
81 
82 // Mapped memory pointers to Rom and Ram areas (Read then Write)
83 // These memory areas must be allocated multiples of the page size
84 // with a 4 byte over-run area lookup for each page (*3 for read, write and fetch)
85 struct SekExt {
86 	UINT8* MemMap[SEK_PAGE_COUNT * 3];
87 
88 	// If MemMap[i] < SEK_MAXHANDLER, use the handler functions
89 	pSekReadByteHandler ReadByte[SEK_MAXHANDLER];
90 	pSekWriteByteHandler WriteByte[SEK_MAXHANDLER];
91 	pSekReadWordHandler ReadWord[SEK_MAXHANDLER];
92 	pSekWriteWordHandler WriteWord[SEK_MAXHANDLER];
93 	pSekReadLongHandler ReadLong[SEK_MAXHANDLER];
94 	pSekWriteLongHandler WriteLong[SEK_MAXHANDLER];
95 
96 	pSekResetCallback ResetCallback;
97 	pSekRTECallback RTECallback;
98 	pSekIrqCallback IrqCallback;
99 	pSekCmpCallback CmpCallback;
100 	pSekTASCallback TASCallback;
101 };
102 
103 #define SEK_DEF_READ_WORD(i, a) { UINT16 d; d = (UINT16)(pSekExt->ReadByte[i](a) << 8); d |= (UINT16)(pSekExt->ReadByte[i]((a) + 1)); return d; }
104 #define SEK_DEF_WRITE_WORD(i, a, d) { pSekExt->WriteByte[i]((a),(UINT8)((d) >> 8)); pSekExt->WriteByte[i]((a) + 1, (UINT8)((d) & 0xff)); }
105 #define SEK_DEF_READ_LONG(i, a) { UINT32 d; d = pSekExt->ReadWord[i](a) << 16; d |= pSekExt->ReadWord[i]((a) + 2); return d; }
106 #define SEK_DEF_WRITE_LONG(i, a, d) { pSekExt->WriteWord[i]((a),(UINT16)((d) >> 16)); pSekExt->WriteWord[i]((a) + 2,(UINT16)((d) & 0xffff)); }
107 
108 extern struct SekExt *SekExt[SEK_MAX], *pSekExt;
109 extern INT32 nSekActive;										// The cpu which is currently being emulated
110 extern INT32 nSekCyclesTotal, nSekCyclesScanline, nSekCyclesSegment, nSekCyclesDone, nSekCyclesToDo;
111 
112 UINT32 SekReadByte(UINT32 a);
113 UINT32 SekReadWord(UINT32 a);
114 UINT32 SekReadLong(UINT32 a);
115 
116 UINT32 SekFetchByte(UINT32 a);
117 UINT32 SekFetchWord(UINT32 a);
118 UINT32 SekFetchLong(UINT32 a);
119 
120 void SekWriteByte(UINT32 a, UINT8 d);
121 void SekWriteWord(UINT32 a, UINT16 d);
122 void SekWriteLong(UINT32 a, UINT32 d);
123 
124 void SekWriteByteROM(UINT32 a, UINT8 d);
125 void SekWriteWordROM(UINT32 a, UINT16 d);
126 void SekWriteLongROM(UINT32 a, UINT32 d);
127 
128 INT32 SekInit(INT32 nCount, INT32 nCPUType);
129 INT32 SekExit();
130 
131 void SekNewFrame();
132 void SekSetCyclesScanline(INT32 nCycles);
133 
134 void SekClose();
135 void SekOpen(const INT32 i);
136 INT32 SekGetActive();
137 INT32 SekShouldInterrupt(); // megadrive
138 void SekBurnUntilInt();
139 
140 void SekCPUPush(INT32 nCPU);
141 void SekCPUPop();
142 INT32 SekCPUGetStackNum();
143 
144 #define SEK_IRQSTATUS_NONE  (0x0000)
145 #define SEK_IRQSTATUS_VAUTO (0x4000)
146 #define SEK_IRQSTATUS_AUTO  (0x2000)
147 #define SEK_IRQSTATUS_ACK   (0x1000)
148 
149 void SekSetIRQLine(const INT32 line, INT32 status);
150 void SekSetIRQLine(INT32 nCPU, const INT32 line, INT32 status);
151 void SekSetVIRQLine(const INT32 line, INT32 nstatus);
152 void SekSetVIRQLine(INT32 nCPU, const INT32 line, INT32 status);
153 
154 void SekReset();
155 void SekReset(INT32 nCPU);
156 
157 void SekRunEnd();
158 void SekRunAdjust(const INT32 nCycles);
159 INT32 SekRun(const INT32 nCycles);
160 INT32 SekRun(INT32 nCPU, INT32 nCycles);
161 void SekSetRESETLine(INT32 nStatus);
162 void SekSetRESETLine(INT32 nCPU, INT32 nStatus);
163 INT32 SekGetRESETLine();
164 INT32 SekGetRESETLine(INT32 nCPU);
165 
166 void SekSetHALT(INT32 nStatus);
167 void SekSetHALT(INT32 nCPU, INT32 nStatus);
168 INT32 SekGetHALT();
169 INT32 SekGetHALT(INT32 nCPU);
170 
171 INT32 SekIdle(INT32 nCPU, INT32 nCycles);
172 
SekIdle(INT32 nCycles)173 inline static INT32 SekIdle(INT32 nCycles)
174 {
175 #if defined FBNEO_DEBUG
176 	extern UINT8 DebugCPU_SekInitted;
177 	if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, (TCHAR*)_T("SekIdle called without init\n"));
178 	if (nSekActive == -1) bprintf(PRINT_ERROR, (TCHAR*)_T("SekIdle called when no CPU open\n"));
179 #endif
180 
181 	nSekCyclesTotal += nCycles;
182 
183 	return nCycles;
184 }
185 
SekSegmentCycles()186 inline static INT32 SekSegmentCycles()
187 {
188 #if defined FBNEO_DEBUG
189 	extern UINT8 DebugCPU_SekInitted;
190 	if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, (TCHAR*)_T("SekSegmentCycles called without init\n"));
191 	if (nSekActive == -1) bprintf(PRINT_ERROR, (TCHAR*)_T("SekSegmentCycles called when no CPU open\n"));
192 #endif
193 
194 #ifdef EMU_M68K
195 	return nSekCyclesDone + nSekCyclesToDo - m68k_ICount;
196 #else
197 	return nSekCyclesDone + nSekCyclesToDo;
198 #endif
199 }
200 
201 INT32 SekTotalCycles(INT32 nCPU);
202 
203 #if defined FBNEO_DEBUG
SekTotalCycles()204 static INT32 SekTotalCycles()
205 #else
206 inline static INT32 SekTotalCycles()
207 #endif
208 {
209 #if defined FBNEO_DEBUG
210 	extern UINT8 DebugCPU_SekInitted;
211 	if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, (TCHAR*)_T("SekTotalCycles called without init\n"));
212 	if (nSekActive == -1) bprintf(PRINT_ERROR, (TCHAR*)_T("SekTotalCycles called when no CPU open\n"));
213 #endif
214 
215 #ifdef EMU_M68K
216 	return nSekCyclesTotal + nSekCyclesToDo - m68k_ICount;
217 #else
218 	return nSekCyclesTotal + nSekCyclesToDo;
219 #endif
220 }
221 
SekCurrentScanline()222 inline static INT32 SekCurrentScanline()
223 {
224 #if defined FBNEO_DEBUG
225 	extern UINT8 DebugCPU_SekInitted;
226 	if (!DebugCPU_SekInitted) bprintf(PRINT_ERROR, (TCHAR*)_T("SekCurrentScanline called without init\n"));
227 	if (nSekActive == -1) bprintf(PRINT_ERROR, (TCHAR*)_T("SekCurrentScanline called when no CPU open\n"));
228 #endif
229 
230 	return SekTotalCycles() / nSekCyclesScanline;
231 }
232 
233 // Mask off address bits (usually top, default is 0xffffff)
234 void SekSetAddressMask(UINT32 nAddressMask);
235 
236 // Map areas of memory
237 INT32 SekMapMemory(UINT8* pMemory, UINT32 nStart, UINT32 nEnd, INT32 nType);
238 INT32 SekMapHandler(uintptr_t nHandler, UINT32 nStart, UINT32 nEnd, INT32 nType);
239 
240 // Set handlers
241 INT32 SekSetReadByteHandler(INT32 i, pSekReadByteHandler pHandler);
242 INT32 SekSetWriteByteHandler(INT32 i, pSekWriteByteHandler pHandler);
243 INT32 SekSetReadWordHandler(INT32 i, pSekReadWordHandler pHandler);
244 INT32 SekSetWriteWordHandler(INT32 i, pSekWriteWordHandler pHandler);
245 INT32 SekSetReadLongHandler(INT32 i, pSekReadLongHandler pHandler);
246 INT32 SekSetWriteLongHandler(INT32 i, pSekWriteLongHandler pHandler);
247 
248 // Set callbacks
249 INT32 SekSetResetCallback(pSekResetCallback pCallback);
250 INT32 SekSetRTECallback(pSekRTECallback pCallback);
251 INT32 SekSetIrqCallback(pSekIrqCallback pCallback);
252 INT32 SekSetCmpCallback(pSekCmpCallback pCallback);
253 INT32 SekSetTASCallback(pSekTASCallback pCallback);
254 
255 // Get a CPU's PC
256 UINT32 SekGetPC(INT32 n);
257 UINT32 SekGetPPC(INT32);
258 
259 INT32 SekScan(INT32 nAction);
260 
261 
262 UINT8 SekCheatRead(UINT32 a); // cheat core
263 
264 extern struct cpu_core_config SekConfig;
265 
266 // depreciate this and use BurnTimerAttach directly!
267 #define BurnTimerAttachSek(clock)	\
268 	BurnTimerAttach(&SekConfig, clock)
269