1 /*** konami: Portable Konami cpu emulator ******************************************
2
3 Copyright Nicola Salmoria and the MAME Team
4
5 Based on M6809 cpu core copyright John Butler
6
7 References:
8
9 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
10
11 m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
12 the 6809 Simulator V09)
13
14 6809 Microcomputer Programming & Interfacing with Experiments"
15 by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
16
17 System dependencies: UINT16 must be 16 bit unsigned int
18 UINT8 must be 8 bit unsigned int
19 UINT32 must be more than 16 bits
20 arrays up to 65536 bytes must be supported
21 machine must be twos complement
22
23 History:
24 991022 HJB:
25 Tried to improve speed: Using bit7 of cycles1 as flag for multi
26 byte opcodes is gone, those opcodes now instead go through opcode2().
27 KONAMI_INLINEd fetch_effective_address() into that function as well.
28 Got rid of the slow/fast flags for stack (S and U) memory accesses.
29 Minor changes to use 32 bit values as arguments to memory functions
30 and added defines for that purpose (e.g. X = 16bit XD = 32bit).
31
32 990720 EHC:
33 Created this file
34
35 *****************************************************************************/
36
37 #include "burnint.h"
38 #include "konami.h"
39 #include "konami_intf.h"
40 #include <stddef.h>
41 #define VERBOSE 0
42
43 #define change_pc(x) PC=x
44 #define logerror printf
45
46 #define LOG(x) do { if (VERBOSE) logerror x; } while (0)
47
48 #define KONAMI_INLINE inline
49
50 /* Konami Registers */
51 typedef struct
52 {
53 PAIR pc; /* Program counter */
54 PAIR ppc; /* Previous program counter */
55 PAIR d; /* Accumulator a and b */
56 PAIR dp; /* Direct Page register (page in MSB) */
57 PAIR u, s; /* Stack pointers */
58 PAIR x, y; /* Index registers */
59 UINT8 cc;
60 UINT8 ireg; /* first opcode */
61 UINT8 irq_state[2];
62 INT32 extra_cycles; /* cycles used up by interrupts */
63 UINT8 int_state; /* SYNC and CWAI flags */
64 UINT8 nmi_state;
65 INT32 nTotalCycles;
66 INT32 hold_irq;
67 int (*irq_callback)(int irqline);
68 void (*setlines_callback)( int lines ); /* callback called when A16-A23 are set */
69 } konami_Regs;
70
71 /* flag bits in the cc register */
72 #define CC_C 0x01 /* Carry */
73 #define CC_V 0x02 /* Overflow */
74 #define CC_Z 0x04 /* Zero */
75 #define CC_N 0x08 /* Negative */
76 #define CC_II 0x10 /* Inhibit IRQ */
77 #define CC_H 0x20 /* Half (auxiliary) carry */
78 #define CC_IF 0x40 /* Inhibit FIRQ */
79 #define CC_E 0x80 /* entire state pushed */
80
81 /* Konami registers */
82 static konami_Regs konami;
83
84 #define pPPC konami.ppc
85 #define pPC konami.pc
86 #define pU konami.u
87 #define pS konami.s
88 #define pX konami.x
89 #define pY konami.y
90 #define pD konami.d
91
92 #define PPC konami.ppc.w.l
93 #define PC konami.pc.w.l
94 #define PCD konami.pc.d
95 #define U konami.u.w.l
96 #define UD konami.u.d
97 #define S konami.s.w.l
98 #define SD konami.s.d
99 #define X konami.x.w.l
100 #define XD konami.x.d
101 #define Y konami.y.w.l
102 #define YD konami.y.d
103 #define D konami.d.w.l
104 #define A konami.d.b.h
105 #define B konami.d.b.l
106 #define DP konami.dp.b.h
107 #define DPD konami.dp.d
108 #define CC konami.cc
109
110 static PAIR ea; /* effective address */
111 #define EA ea.w.l
112 #define EAD ea.d
113
114 #define KONAMI_CWAI 8 /* set when CWAI is waiting for an interrupt */
115 #define KONAMI_SYNC 16 /* set when SYNC is waiting for an interrupt */
116 #define KONAMI_LDS 32 /* set when LDS occured at least once */
117
118 static int nCyclesToDo = 0;
119
120 #define CHECK_IRQ_LINES \
121 if( konami.irq_state[KONAMI_IRQ_LINE] != CPU_IRQSTATUS_NONE || \
122 konami.irq_state[KONAMI_FIRQ_LINE] != CPU_IRQSTATUS_NONE ) \
123 konami.int_state &= ~KONAMI_SYNC; /* clear SYNC flag */ \
124 if( konami.irq_state[KONAMI_FIRQ_LINE]!=CPU_IRQSTATUS_NONE && !(CC & CC_IF) ) \
125 { \
126 /* fast IRQ */ \
127 /* state already saved by CWAI? */ \
128 if( konami.int_state & KONAMI_CWAI ) \
129 { \
130 konami.int_state &= ~KONAMI_CWAI; /* clear CWAI */ \
131 konami.extra_cycles += 7; /* subtract +7 cycles */ \
132 } \
133 else \
134 { \
135 CC &= ~CC_E; /* save 'short' state */ \
136 PUSHWORD(pPC); \
137 PUSHBYTE(CC); \
138 konami.extra_cycles += 10; /* subtract +10 cycles */ \
139 } \
140 CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */ \
141 PCD = RM16(0xfff6); \
142 change_pc(PC); /* TS 971002 */ \
143 if (konami.hold_irq == (1 << KONAMI_FIRQ_LINE)) { \
144 konami.hold_irq &= ~(1 << KONAMI_FIRQ_LINE); \
145 konami.irq_state[KONAMI_FIRQ_LINE] = 0; \
146 } \
147 (void)(*konami.irq_callback)(KONAMI_FIRQ_LINE); \
148 } \
149 else \
150 if( konami.irq_state[KONAMI_IRQ_LINE]!=CPU_IRQSTATUS_NONE && !(CC & CC_II) )\
151 { \
152 /* standard IRQ */ \
153 /* state already saved by CWAI? */ \
154 if( konami.int_state & KONAMI_CWAI ) \
155 { \
156 konami.int_state &= ~KONAMI_CWAI; /* clear CWAI flag */ \
157 konami.extra_cycles += 7; /* subtract +7 cycles */ \
158 } \
159 else \
160 { \
161 CC |= CC_E; /* save entire state */ \
162 PUSHWORD(pPC); \
163 PUSHWORD(pU); \
164 PUSHWORD(pY); \
165 PUSHWORD(pX); \
166 PUSHBYTE(DP); \
167 PUSHBYTE(B); \
168 PUSHBYTE(A); \
169 PUSHBYTE(CC); \
170 konami.extra_cycles += 19; /* subtract +19 cycles */ \
171 } \
172 CC |= CC_II; /* inhibit IRQ */ \
173 PCD = RM16(0xfff8); \
174 change_pc(PC); /* TS 971002 */ \
175 if (konami.hold_irq == (1 << KONAMI_IRQ_LINE)) { \
176 konami.hold_irq &= ~(1 << KONAMI_IRQ_LINE); \
177 konami.irq_state[KONAMI_IRQ_LINE] = 0; \
178 } \
179 (void)(*konami.irq_callback)(KONAMI_IRQ_LINE); \
180 }
181
182 /* public globals */
183 static int konami_ICount;
184 //int konami_Flags; /* flags for speed optimization (obsolete!!) */
185
186 /* these are re-defined in konami.h TO RAM, ROM or functions in memory.c */
187 #define RM(Addr) KONAMI_RDMEM(Addr)
188 #define WM(Addr,Value) KONAMI_WRMEM(Addr,Value)
189 #define ROP(Addr) KONAMI_RDOP(Addr)
190 #define ROP_ARG(Addr) KONAMI_RDOP_ARG(Addr)
191
192 #define SIGNED(a) (UINT16)(INT16)(INT8)(a)
193
194 /* macros to access memory */
195 #define IMMBYTE(b) { b = ROP_ARG(PCD); PC++; }
196 #define IMMWORD(w) { w.d = (ROP_ARG(PCD)<<8) | ROP_ARG(PCD+1); PC += 2; }
197
198 #define PUSHBYTE(b) --S; WM(SD,b)
199 #define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h)
200 #define PULLBYTE(b) b=KONAMI_RDMEM(SD); S++
201 #define PULLWORD(w) w=KONAMI_RDMEM(SD)<<8; S++; w|=KONAMI_RDMEM(SD); S++
202
203 #define PSHUBYTE(b) --U; WM(UD,b);
204 #define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h)
205 #define PULUBYTE(b) b=KONAMI_RDMEM(UD); U++
206 #define PULUWORD(w) w=KONAMI_RDMEM(UD)<<8; U++; w|=KONAMI_RDMEM(UD); U++
207
208 #define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
209 #define CLR_NZV CC&=~(CC_N|CC_Z|CC_V)
210 #define CLR_NZ CC&=~(CC_N|CC_Z)
211 #define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C)
212 #define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C)
213 #define CLR_Z CC&=~(CC_Z)
214 #define CLR_NZC CC&=~(CC_N|CC_Z|CC_C)
215 #define CLR_ZC CC&=~(CC_Z|CC_C)
216
217 /* macros for CC -- CC bits affected should be reset before calling */
218 #define SET_Z(a) if(!a)SEZ
219 #define SET_Z8(a) SET_Z((UINT8)a)
220 #define SET_Z16(a) SET_Z((UINT16)a)
221 #define SET_N8(a) CC|=((a&0x80)>>4)
222 #define SET_N16(a) CC|=((a&0x8000)>>12)
223 #define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1)
224 #define SET_C8(a) CC|=((a&0x100)>>8)
225 #define SET_C16(a) CC|=((a&0x10000)>>16)
226 #define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6)
227 #define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14)
228
229 static const UINT8 flags8i[256]= /* increment */
230 {
231 CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
233 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
234 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
235 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
236 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
237 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
238 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
239 CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
240 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
241 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
242 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
243 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
244 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
245 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
246 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
247 };
248 static const UINT8 flags8d[256]= /* decrement */
249 {
250 CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
253 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
254 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
255 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
256 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
257 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V,
258 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
259 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
260 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
261 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
262 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
263 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
264 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
265 CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
266 };
267 #define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
268 #define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
269
270 /* combos */
271 #define SET_NZ8(a) {SET_N8(a);SET_Z(a);}
272 #define SET_NZ16(a) {SET_N16(a);SET_Z(a);}
273 #define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
274 #define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
275
276 /* macros for addressing modes (postbytes have their own code) */
277 #define DIRECT EAD = DPD; IMMBYTE(ea.b.l)
278 #define IMM8 EAD = PCD; PC++
279 #define IMM16 EAD = PCD; PC+=2
280 #define EXTENDED IMMWORD(ea)
281
282 /* macros to set status flags */
283 #if defined(SEC)
284 #undef SEC
285 #endif
286 #define SEC CC|=CC_C
287 #define CLC CC&=~CC_C
288 #define SEZ CC|=CC_Z
289 #define CLZ CC&=~CC_Z
290 #define SEN CC|=CC_N
291 #define CLN CC&=~CC_N
292 #define SEV CC|=CC_V
293 #define CLV CC&=~CC_V
294 #define SEH CC|=CC_H
295 #define CLH CC&=~CC_H
296
297 /* macros for convenience */
298 #define DIRBYTE(b) DIRECT; b=RM(EAD)
299 #define DIRWORD(w) DIRECT; w.d=RM16(EAD)
300 #define EXTBYTE(b) EXTENDED; b=RM(EAD)
301 #define EXTWORD(w) EXTENDED; w.d=RM16(EAD)
302
303 /* macros for branch instructions */
304 #define BRANCH(f) { \
305 UINT8 t; \
306 IMMBYTE(t); \
307 if( f ) \
308 { \
309 PC += SIGNED(t); \
310 change_pc(PC); /* TS 971002 */ \
311 } \
312 }
313
314 #define LBRANCH(f) { \
315 PAIR t; \
316 IMMWORD(t); \
317 if( f ) \
318 { \
319 konami_ICount -= 1; \
320 PC += t.w.l; \
321 change_pc(PC); /* TS 971002 */ \
322 } \
323 }
324
325 #define NXORV ((CC&CC_N)^((CC&CC_V)<<2))
326
327 /* macros for setting/getting registers in TFR/EXG instructions */
328 #define GETREG(val,reg) \
329 switch(reg) { \
330 case 0: val = A; break; \
331 case 1: val = B; break; \
332 case 2: val = X; break; \
333 case 3: val = Y; break; \
334 case 4: val = S; break; /* ? */ \
335 case 5: val = U; break; \
336 default: val = 0xff; logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
337 }
338
339 #define SETREG(val,reg) \
340 switch(reg) { \
341 case 0: A = val; break; \
342 case 1: B = val; break; \
343 case 2: X = val; break; \
344 case 3: Y = val; break; \
345 case 4: S = val; break; /* ? */ \
346 case 5: U = val; break; \
347 default: logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
348 }
349
350 /* opcode timings */
351 static const UINT8 cycles1[] =
352 {
353 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
354 /*0*/ 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5,
355 /*1*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
356 /*2*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
357 /*3*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 7, 6,
358 /*4*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
359 /*5*/ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 1, 1, 1,
360 /*6*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
361 /*7*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
362 /*8*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
363 /*9*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
364 /*A*/ 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 2, 1,
365 /*B*/ 3, 2, 2,11,22,11, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3,
366 /*C*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2,
367 /*D*/ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
368 /*E*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
369 /*F*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
370 };
371
RM16(UINT32 Addr)372 KONAMI_INLINE UINT32 RM16( UINT32 Addr )
373 {
374 UINT32 result = RM(Addr) << 8;
375 return result | RM((Addr+1)&0xffff);
376 }
377
WM16(UINT32 Addr,PAIR * p)378 KONAMI_INLINE void WM16( UINT32 Addr, PAIR *p )
379 {
380 WM( Addr, p->b.h );
381 WM( (Addr+1)&0xffff, p->b.l );
382 }
383
384 /****************************************************************************
385 * Get all registers in given buffer
386 ****************************************************************************/
387 #if 0
388 static void konami_get_context(void *dst)
389 {
390 if( dst )
391 *(konami_Regs*)dst = konami;
392 }
393 #endif
394
395 /****************************************************************************
396 * Set all registers to given values
397 ****************************************************************************/
398 #if 0
399 static void konami_set_context(void *src)
400 {
401 if( src )
402 konami = *(konami_Regs*)src;
403 change_pc(PC); /* TS 971002 */
404
405 CHECK_IRQ_LINES;
406 }
407 #endif
408
409 /****************************************************************************/
410 /* Reset registers to their initial values */
411 /****************************************************************************/
konami_init(int (* irqcallback)(int))412 void konami_init(int (*irqcallback)(int))
413 {
414 konami.irq_callback = irqcallback;
415 }
416
konamiReset()417 void konamiReset()
418 {
419 #if defined FBNEO_DEBUG
420 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiReset called without init\n"));
421 #endif
422
423 konami.nTotalCycles = 0;
424 konami.int_state = 0;
425 konami.nmi_state = CPU_IRQSTATUS_NONE;
426 konami.irq_state[0] = CPU_IRQSTATUS_NONE;
427 konami.irq_state[1] = CPU_IRQSTATUS_NONE;
428
429 DPD = 0; /* Reset direct page register */
430
431 CC |= CC_II; /* IRQ disabled */
432 CC |= CC_IF; /* FIRQ disabled */
433
434 PCD = RM16(0xfffe);
435 change_pc(PC); /* TS 971002 */
436 }
437
438 #if 0
439 static void konami_exit(void)
440 {
441 }
442 #endif
443
444 /* Generate interrupts */
445 /****************************************************************************
446 * Set IRQ line state
447 ****************************************************************************/
konami_set_irq_hold(INT32 irq)448 void konami_set_irq_hold(INT32 irq)
449 {
450 konami.hold_irq = 1 << irq;
451 }
452
konami_set_irq_line(int irqline,int state)453 void konami_set_irq_line(int irqline, int state)
454 {
455 #if defined FBNEO_DEBUG
456 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konami_set_irq_line called without init\n"));
457 #endif
458
459 if (irqline == KONAMI_INPUT_LINE_NMI)
460 {
461 if (konami.nmi_state == state) return;
462 konami.nmi_state = state;
463 // LOG(("KONAMI#%d set_nmi_line %d\n", cpu_getactivecpu(), state));
464 if( state == CPU_IRQSTATUS_NONE ) return;
465
466 /* if the stack was not yet initialized */
467 if( !(konami.int_state & KONAMI_LDS) ) return;
468
469 konami.int_state &= ~KONAMI_SYNC;
470 /* state already saved by CWAI? */
471 if( konami.int_state & KONAMI_CWAI )
472 {
473 konami.int_state &= ~KONAMI_CWAI;
474 konami.extra_cycles += 7; /* subtract +7 cycles next time */
475 }
476 else
477 {
478 CC |= CC_E; /* save entire state */
479 PUSHWORD(pPC);
480 PUSHWORD(pU);
481 PUSHWORD(pY);
482 PUSHWORD(pX);
483 PUSHBYTE(DP);
484 PUSHBYTE(B);
485 PUSHBYTE(A);
486 PUSHBYTE(CC);
487 konami.extra_cycles += 19; /* subtract +19 cycles next time */
488 }
489 CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
490 PCD = RM16(0xfffc);
491 change_pc(PC); /* TS 971002 */
492 }
493 else if (irqline < 2)
494 {
495 // LOG(("KONAMI#%d set_irq_line %d, %d\n", cpu_getactivecpu(), irqline, state));
496 konami.irq_state[irqline] = state;
497 if (state == CPU_IRQSTATUS_NONE) return;
498 CHECK_IRQ_LINES;
499 }
500 }
501
502 /* includes the static function prototypes and the master opcode table */
503 #include "konamtbl.c"
504
505 /* includes the actual opcode implementations */
506 #include "konamops.c"
507
508 static int end_run = 0;
509
510 /* execute instructions on this CPU until icount expires */
konamiRun(int cycles)511 int konamiRun(int cycles)
512 {
513 #if defined FBNEO_DEBUG
514 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiRun called without init\n"));
515 #endif
516
517 konami_ICount = cycles - konami.extra_cycles;
518 nCyclesToDo = cycles;
519 konami.extra_cycles = 0;
520
521 end_run = 0;
522
523 if( konami.int_state & (KONAMI_CWAI | KONAMI_SYNC) )
524 {
525 konami_ICount = 0;
526 }
527 else
528 {
529 do
530 {
531 pPPC = pPC;
532
533 konami.ireg = ROP(PCD);
534 PC++;
535
536 (*konami_main[konami.ireg])();
537
538 konami_ICount -= cycles1[konami.ireg];
539
540 } while( konami_ICount > 0 && !end_run );
541
542 konami_ICount -= konami.extra_cycles;
543 konami.extra_cycles = 0;
544 }
545
546 cycles = cycles - konami_ICount;
547 konami.nTotalCycles += cycles;
548 nCyclesToDo = konami_ICount = 0;
549
550 return cycles;
551 }
552
konamiCpuScan(int nAction)553 int konamiCpuScan(int nAction)
554 {
555 #if defined FBNEO_DEBUG
556 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiCpuScan called without init\n"));
557 #endif
558
559 if (nAction & ACB_DRIVER_DATA) {
560 struct BurnArea ba;
561
562 memset(&ba, 0, sizeof(ba));
563 ba.Data = (unsigned char*)&konami;
564 ba.nLen = STRUCT_SIZE_HELPER(konami_Regs, hold_irq);
565 ba.szName = "KonamiCPU Registers";
566 BurnAcb(&ba);
567
568 SCAN_VAR(ea);
569 }
570
571 return 0;
572 }
573
konamiRunEnd()574 void konamiRunEnd()
575 {
576 #if defined FBNEO_DEBUG
577 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiRunEnd called without init\n"));
578 #endif
579
580 end_run = 1;
581 }
582
konamiIdle(INT32 cycles)583 INT32 konamiIdle(INT32 cycles)
584 {
585 #if defined FBNEO_DEBUG
586 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiIdle called without init\n"));
587 #endif
588 konami_ICount -= cycles;
589
590 return konami_ICount;
591 }
592
konamiSetlinesCallback(void (* setlines_callback)(int lines))593 void konamiSetlinesCallback(void (*setlines_callback)(int lines))
594 {
595 #if defined FBNEO_DEBUG
596 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiSetlinesCallback called without init\n"));
597 #endif
598
599 konami.setlines_callback = setlines_callback;
600 }
601
konamiTotalCycles()602 int konamiTotalCycles()
603 {
604 #if defined FBNEO_DEBUG
605 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiTotalCycles called without init\n"));
606 #endif
607
608 return konami.nTotalCycles + (nCyclesToDo - konami_ICount);
609 }
610
konamiNewFrame()611 void konamiNewFrame()
612 {
613 #if defined FBNEO_DEBUG
614 if (!DebugCPU_KonamiInitted) bprintf(PRINT_ERROR, _T("konamiNewFrame called without init\n"));
615 #endif
616
617 konami.nTotalCycles = 0;
618 }
619