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