1 /*** konami: Portable Konami cpu emulator ******************************************
2 
3 	Copyright (C) The MAME Team 1999
4 
5 	Based on M6809 cpu core	copyright (C) John Butler 1997
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 	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 <stdio.h>
38 #include <stdlib.h>
39 #include "cpuintrf.h"
40 #include "state.h"
41 #include "mamedbg.h"
42 #include "konami.h"
43 
44 static UINT8 konami_reg_layout[] = {
45 	KONAMI_PC, KONAMI_S, KONAMI_CC, KONAMI_A, KONAMI_B, KONAMI_X, -1,
46 	KONAMI_Y, KONAMI_U, KONAMI_DP, KONAMI_NMI_STATE, KONAMI_IRQ_STATE, KONAMI_FIRQ_STATE, 0
47 };
48 
49 /* Layout of the debugger windows x,y,w,h */
50 static UINT8 konami_win_layout[] = {
51 	27, 0,53, 4,	/* register window (top, right rows) */
52 	 0, 0,26,22,	/* disassembler window (left colums) */
53 	27, 5,53, 8,	/* memory #1 window (right, upper middle) */
54 	27,14,53, 8,	/* memory #2 window (right, lower middle) */
55 	 0,23,80, 1,	/* command line window (bottom rows) */
56 };
57 
58 /* Konami Registers */
59 typedef struct
60 {
61 	PAIR	pc; 		/* Program counter */
62     PAIR    ppc;        /* Previous program counter */
63     PAIR    d;          /* Accumulator a and b */
64     PAIR    dp;         /* Direct Page register (page in MSB) */
65 	PAIR	u, s;		/* Stack pointers */
66 	PAIR	x, y;		/* Index registers */
67     UINT8   cc;
68 	UINT8	ireg;		/* first opcode */
69     UINT8   irq_state[2];
70     int     extra_cycles; /* cycles used up by interrupts */
71     int     (*irq_callback)(int irqline);
72     UINT8   int_state;  /* SYNC and CWAI flags */
73 	UINT8	nmi_state;
74 } konami_Regs;
75 
76 /* flag bits in the cc register */
77 #define CC_C    0x01        /* Carry */
78 #define CC_V    0x02        /* Overflow */
79 #define CC_Z    0x04        /* Zero */
80 #define CC_N    0x08        /* Negative */
81 #define CC_II   0x10        /* Inhibit IRQ */
82 #define CC_H    0x20        /* Half (auxiliary) carry */
83 #define CC_IF   0x40        /* Inhibit FIRQ */
84 #define CC_E    0x80        /* entire state pushed */
85 
86 /* Konami registers */
87 static konami_Regs konami;
88 
89 #define	pPPC    konami.ppc
90 #define pPC 	konami.pc
91 #define pU		konami.u
92 #define pS		konami.s
93 #define pX		konami.x
94 #define pY		konami.y
95 #define pD		konami.d
96 
97 #define	PPC		konami.ppc.w.l
98 #define PC  	konami.pc.w.l
99 #define PCD 	konami.pc.d
100 #define U		konami.u.w.l
101 #define UD		konami.u.d
102 #define S		konami.s.w.l
103 #define SD		konami.s.d
104 #define X		konami.x.w.l
105 #define XD		konami.x.d
106 #define Y		konami.y.w.l
107 #define YD		konami.y.d
108 #define D   	konami.d.w.l
109 #define A   	konami.d.b.h
110 #define B		konami.d.b.l
111 #define DP		konami.dp.b.h
112 #define DPD 	konami.dp.d
113 #define CC  	konami.cc
114 
115 static PAIR ea;         /* effective address */
116 #define EA	ea.w.l
117 #define EAD ea.d
118 
119 #define KONAMI_CWAI		8	/* set when CWAI is waiting for an interrupt */
120 #define KONAMI_SYNC		16	/* set when SYNC is waiting for an interrupt */
121 #define KONAMI_LDS		32	/* set when LDS occured at least once */
122 
123 #define CHECK_IRQ_LINES 												\
124 	if( konami.irq_state[KONAMI_IRQ_LINE] != CLEAR_LINE ||				\
125 		konami.irq_state[KONAMI_FIRQ_LINE] != CLEAR_LINE )				\
126 		konami.int_state &= ~KONAMI_SYNC; /* clear SYNC flag */			\
127 	if( konami.irq_state[KONAMI_FIRQ_LINE]!=CLEAR_LINE && !(CC & CC_IF) ) \
128 	{																	\
129 		/* fast IRQ */													\
130 		/* state already saved by CWAI? */								\
131 		if( konami.int_state & KONAMI_CWAI )							\
132 		{																\
133 			konami.int_state &= ~KONAMI_CWAI;  /* clear CWAI */			\
134 			konami.extra_cycles += 7;		 /* subtract +7 cycles */	\
135         }                                                               \
136 		else															\
137 		{																\
138 			CC &= ~CC_E;				/* save 'short' state */        \
139 			PUSHWORD(pPC);												\
140 			PUSHBYTE(CC);												\
141 			konami.extra_cycles += 10;	/* subtract +10 cycles */		\
142 		}																\
143 		CC |= CC_IF | CC_II;			/* inhibit FIRQ and IRQ */		\
144 		PCD = RM16(0xfff6); 											\
145 		change_pc16(PC);					/* TS 971002 */ 				\
146 		(void)(*konami.irq_callback)(KONAMI_FIRQ_LINE);					\
147 	}																	\
148 	else																\
149 	if( konami.irq_state[KONAMI_IRQ_LINE]!=CLEAR_LINE && !(CC & CC_II) )\
150 	{																	\
151 		/* standard IRQ */												\
152 		/* state already saved by CWAI? */								\
153 		if( konami.int_state & KONAMI_CWAI )							\
154 		{																\
155 			konami.int_state &= ~KONAMI_CWAI;  /* clear CWAI flag */	\
156 			konami.extra_cycles += 7;		 /* subtract +7 cycles */	\
157 		}																\
158 		else															\
159 		{																\
160 			CC |= CC_E; 				/* save entire state */ 		\
161 			PUSHWORD(pPC);												\
162 			PUSHWORD(pU);												\
163 			PUSHWORD(pY);												\
164 			PUSHWORD(pX);												\
165 			PUSHBYTE(DP);												\
166 			PUSHBYTE(B);												\
167 			PUSHBYTE(A);												\
168 			PUSHBYTE(CC);												\
169 			konami.extra_cycles += 19;	 /* subtract +19 cycles */		\
170 		}																\
171 		CC |= CC_II;					/* inhibit IRQ */				\
172 		PCD = RM16(0xfff8); 											\
173 		change_pc16(PC);					/* TS 971002 */ 				\
174 		(void)(*konami.irq_callback)(KONAMI_IRQ_LINE);					\
175 	}
176 
177 /* public globals */
178 int konami_ICount=50000;
179 int konami_Flags;	/* flags for speed optimization (obsolete!!) */
180 void (*konami_cpu_setlines_callback)( int lines ) = 0; /* callback called when A16-A23 are set */
181 
182 /* these are re-defined in konami.h TO RAM, ROM or functions in memory.c */
183 #define RM(Addr)			KONAMI_RDMEM(Addr)
184 #define WM(Addr,Value)		KONAMI_WRMEM(Addr,Value)
185 #define ROP(Addr)			KONAMI_RDOP(Addr)
186 #define ROP_ARG(Addr)		KONAMI_RDOP_ARG(Addr)
187 
188 #define SIGNED(a)	(UINT16)(INT16)(INT8)(a)
189 
190 /* macros to access memory */
191 #define IMMBYTE(b)	{ b = ROP_ARG(PCD); PC++; }
192 #define IMMWORD(w)	{ w.d = (ROP_ARG(PCD)<<8) | ROP_ARG(PCD+1); PC += 2; }
193 
194 #define PUSHBYTE(b) --S; WM(SD,b)
195 #define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h)
196 #define PULLBYTE(b) b=KONAMI_RDMEM(SD); S++
197 #define PULLWORD(w) w=KONAMI_RDMEM(SD)<<8; S++; w|=KONAMI_RDMEM(SD); S++
198 
199 #define PSHUBYTE(b) --U; WM(UD,b);
200 #define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h)
201 #define PULUBYTE(b) b=KONAMI_RDMEM(UD); U++
202 #define PULUWORD(w) w=KONAMI_RDMEM(UD)<<8; U++; w|=KONAMI_RDMEM(UD); U++
203 
204 #define CLR_HNZVC	CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
205 #define CLR_NZV 	CC&=~(CC_N|CC_Z|CC_V)
206 #define CLR_NZ		CC&=~(CC_N|CC_Z)
207 #define CLR_HNZC	CC&=~(CC_H|CC_N|CC_Z|CC_C)
208 #define CLR_NZVC	CC&=~(CC_N|CC_Z|CC_V|CC_C)
209 #define CLR_Z		CC&=~(CC_Z)
210 #define CLR_NZC 	CC&=~(CC_N|CC_Z|CC_C)
211 #define CLR_ZC		CC&=~(CC_Z|CC_C)
212 
213 /* macros for CC -- CC bits affected should be reset before calling */
214 #define SET_Z(a)		if(!a)SEZ
215 #define SET_Z8(a)		SET_Z((UINT8)a)
216 #define SET_Z16(a)		SET_Z((UINT16)a)
217 #define SET_N8(a)		CC|=((a&0x80)>>4)
218 #define SET_N16(a)		CC|=((a&0x8000)>>12)
219 #define SET_H(a,b,r)	CC|=(((a^b^r)&0x10)<<1)
220 #define SET_C8(a)		CC|=((a&0x100)>>8)
221 #define SET_C16(a)		CC|=((a&0x10000)>>16)
222 #define SET_V8(a,b,r)	CC|=(((a^b^r^(r>>1))&0x80)>>6)
223 #define SET_V16(a,b,r)	CC|=(((a^b^r^(r>>1))&0x8000)>>14)
224 
225 static UINT8 flags8i[256]=	 /* increment */
226 {
227 CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
228 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
229 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
231 0x00,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 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,
236 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,
237 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,
238 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,
239 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,
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 };
244 static UINT8 flags8d[256]= /* decrement */
245 {
246 CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
247 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
248 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
249 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250 0x00,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,CC_V,
254 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,
255 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,
256 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,
257 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,
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 };
263 #define SET_FLAGS8I(a)		{CC|=flags8i[(a)&0xff];}
264 #define SET_FLAGS8D(a)		{CC|=flags8d[(a)&0xff];}
265 
266 /* combos */
267 #define SET_NZ8(a)			{SET_N8(a);SET_Z(a);}
268 #define SET_NZ16(a)			{SET_N16(a);SET_Z(a);}
269 #define SET_FLAGS8(a,b,r)	{SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
270 #define SET_FLAGS16(a,b,r)	{SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
271 
272 /* macros for addressing modes (postbytes have their own code) */
273 #define DIRECT	EAD = DPD; IMMBYTE(ea.b.l)
274 #define IMM8	EAD = PCD; PC++
275 #define IMM16	EAD = PCD; PC+=2
276 #define EXTENDED IMMWORD(ea)
277 
278 /* macros to set status flags */
279 #define SEC CC|=CC_C
280 #define CLC CC&=~CC_C
281 #define SEZ CC|=CC_Z
282 #define CLZ CC&=~CC_Z
283 #define SEN CC|=CC_N
284 #define CLN CC&=~CC_N
285 #define SEV CC|=CC_V
286 #define CLV CC&=~CC_V
287 #define SEH CC|=CC_H
288 #define CLH CC&=~CC_H
289 
290 /* macros for convenience */
291 #define DIRBYTE(b) DIRECT; b=RM(EAD)
292 #define DIRWORD(w) DIRECT; w.d=RM16(EAD)
293 #define EXTBYTE(b) EXTENDED; b=RM(EAD)
294 #define EXTWORD(w) EXTENDED; w.d=RM16(EAD)
295 
296 /* macros for branch instructions */
297 #define BRANCH(f) { 					\
298 	UINT8 t;							\
299 	IMMBYTE(t); 						\
300 	if( f ) 							\
301 	{									\
302 		PC += SIGNED(t);				\
303 		change_pc16(PC);	/* TS 971002 */ \
304 	}									\
305 }
306 
307 #define LBRANCH(f) {                    \
308 	PAIR t; 							\
309 	IMMWORD(t); 						\
310 	if( f ) 							\
311 	{									\
312 		konami_ICount -= 1;				\
313 		PC += t.w.l;					\
314 		change_pc16(PC);	/* TS 971002 */ \
315 	}									\
316 }
317 
318 #define NXORV  ((CC&CC_N)^((CC&CC_V)<<2))
319 
320 /* macros for setting/getting registers in TFR/EXG instructions */
321 #define GETREG(val,reg) 				\
322 	switch(reg) {						\
323 	case 0: val = A;	break;			\
324 	case 1: val = B; 	break; 			\
325 	case 2: val = X; 	break;			\
326 	case 3: val = Y;	break; 			\
327 	case 4: val = S; 	break; /* ? */	\
328 	case 5: val = U;	break;			\
329 	default: val = 0xff; log_cb(RETRO_LOG_DEBUG, LOGPRE "Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
330 }
331 
332 #define SETREG(val,reg) 				\
333 	switch(reg) {						\
334 	case 0: A = val;	break;			\
335 	case 1: B = val;	break;			\
336 	case 2: X = val; 	break;			\
337 	case 3: Y = val;	break;			\
338 	case 4: S = val;	break; /* ? */	\
339 	case 5: U = val; 	break;			\
340 	default: log_cb(RETRO_LOG_DEBUG, LOGPRE "Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
341 }
342 
343 /* opcode timings */
344 static UINT8 cycles1[] =
345 {
346 	/*	 0	1  2  3  4	5  6  7  8	9  A  B  C	D  E  F */
347   /*0*/  1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5,
348   /*1*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
349   /*2*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
350   /*3*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 7, 6,
351   /*4*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
352   /*5*/  4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 1, 1, 1,
353   /*6*/  3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
354   /*7*/  3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
355   /*8*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
356   /*9*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
357   /*A*/  2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 2, 1,
358   /*B*/  3, 2, 2,11,22,11, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3,
359   /*C*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2,
360   /*D*/  2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
361   /*E*/  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
362   /*F*/  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
363 };
364 
RM16(UINT32 Addr)365 static INLINE UINT32 RM16( UINT32 Addr )
366 {
367 	UINT32 result = RM(Addr) << 8;
368 	return result | RM((Addr+1)&0xffff);
369 }
370 
WM16(UINT32 Addr,PAIR * p)371 static INLINE void WM16( UINT32 Addr, PAIR *p )
372 {
373 	WM( Addr, p->b.h );
374 	WM( (Addr+1)&0xffff, p->b.l );
375 }
376 
377 /****************************************************************************
378  * Get all registers in given buffer
379  ****************************************************************************/
konami_get_context(void * dst)380 unsigned konami_get_context(void *dst)
381 {
382 	if( dst )
383 		*(konami_Regs*)dst = konami;
384 	return sizeof(konami_Regs);
385 }
386 
387 /****************************************************************************
388  * Set all registers to given values
389  ****************************************************************************/
konami_set_context(void * src)390 void konami_set_context(void *src)
391 {
392 	if( src )
393 		konami = *(konami_Regs*)src;
394     change_pc16(PC);    /* TS 971002 */
395 
396     CHECK_IRQ_LINES;
397 }
398 
399 /****************************************************************************/
400 /* Return a specific register                                               */
401 /****************************************************************************/
konami_get_reg(int regnum)402 unsigned konami_get_reg(int regnum)
403 {
404 	switch( regnum )
405 	{
406 		case REG_PC:
407 		case KONAMI_PC: return PC;
408 		case REG_SP:
409 		case KONAMI_S: return S;
410 		case KONAMI_CC: return CC;
411 		case KONAMI_U: return U;
412 		case KONAMI_A: return A;
413 		case KONAMI_B: return B;
414 		case KONAMI_X: return X;
415 		case KONAMI_Y: return Y;
416 		case KONAMI_DP: return DP;
417 		case KONAMI_NMI_STATE: return konami.nmi_state;
418 		case KONAMI_IRQ_STATE: return konami.irq_state[KONAMI_IRQ_LINE];
419 		case KONAMI_FIRQ_STATE: return konami.irq_state[KONAMI_FIRQ_LINE];
420 		case REG_PREVIOUSPC: return PPC;
421 		default:
422 			if( regnum <= REG_SP_CONTENTS )
423 			{
424 				unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
425 				if( offset < 0xffff )
426 					return ( RM( offset ) << 8 ) | RM( offset + 1 );
427 			}
428 	}
429 	return 0;
430 }
431 
432 
433 /****************************************************************************/
434 /* Set a specific register                                                  */
435 /****************************************************************************/
konami_set_reg(int regnum,unsigned val)436 void konami_set_reg(int regnum, unsigned val)
437 {
438 	switch( regnum )
439 	{
440 		case REG_PC:
441 		case KONAMI_PC: PC = val; change_pc16(PC); break;
442 		case REG_SP:
443 		case KONAMI_S: S = val; break;
444 		case KONAMI_CC: CC = val; CHECK_IRQ_LINES; break;
445 		case KONAMI_U: U = val; break;
446 		case KONAMI_A: A = val; break;
447 		case KONAMI_B: B = val; break;
448 		case KONAMI_X: X = val; break;
449 		case KONAMI_Y: Y = val; break;
450 		case KONAMI_DP: DP = val; break;
451 		case KONAMI_NMI_STATE: konami.nmi_state = val; break;
452 		case KONAMI_IRQ_STATE: konami.irq_state[KONAMI_IRQ_LINE] = val; break;
453 		case KONAMI_FIRQ_STATE: konami.irq_state[KONAMI_FIRQ_LINE] = val; break;
454 		default:
455 			if( regnum <= REG_SP_CONTENTS )
456 			{
457 				unsigned offset = S + 2 * (REG_SP_CONTENTS - regnum);
458 				if( offset < 0xffff )
459 				{
460 					WM( offset, (val >> 8) & 0xff );
461 					WM( offset+1, val & 0xff );
462 				}
463 			}
464     }
465 }
466 
467 
468 /****************************************************************************/
469 /* Reset registers to their initial values									*/
470 /****************************************************************************/
konami_init(void)471 void konami_init(void)
472 {
473 }
474 
konami_reset(void * param)475 void konami_reset(void *param)
476 {
477 	konami.int_state = 0;
478 	konami.nmi_state = CLEAR_LINE;
479 	konami.irq_state[0] = CLEAR_LINE;
480 	konami.irq_state[0] = CLEAR_LINE;
481 
482 	DPD = 0;			/* Reset direct page register */
483 
484     CC |= CC_II;        /* IRQ disabled */
485     CC |= CC_IF;        /* FIRQ disabled */
486 
487 	PCD = RM16(0xfffe);
488     change_pc16(PC);    /* TS 971002 */
489 }
490 
konami_exit(void)491 void konami_exit(void)
492 {
493 	/* just make sure we deinit this, so the next game set its own */
494 	konami_cpu_setlines_callback = 0;
495 }
496 
497 /* Generate interrupts */
498 /****************************************************************************
499  * Set IRQ line state
500  ****************************************************************************/
konami_set_irq_line(int irqline,int state)501 void konami_set_irq_line(int irqline, int state)
502 {
503 	if (irqline == IRQ_LINE_NMI)
504 	{
505 		if (konami.nmi_state == state) return;
506 		konami.nmi_state = state;
507 		log_cb(RETRO_LOG_DEBUG, LOGPRE "KONAMI#%d set_nmi_line %d\n", cpu_getactivecpu(), state);
508 		if( state == CLEAR_LINE ) return;
509 
510 		/* if the stack was not yet initialized */
511 	    if( !(konami.int_state & KONAMI_LDS) ) return;
512 
513 	    konami.int_state &= ~KONAMI_SYNC;
514 		/* state already saved by CWAI? */
515 		if( konami.int_state & KONAMI_CWAI )
516 		{
517 			konami.int_state &= ~KONAMI_CWAI;
518 			konami.extra_cycles += 7;	/* subtract +7 cycles next time */
519 	    }
520 		else
521 		{
522 			CC |= CC_E; 				/* save entire state */
523 			PUSHWORD(pPC);
524 			PUSHWORD(pU);
525 			PUSHWORD(pY);
526 			PUSHWORD(pX);
527 			PUSHBYTE(DP);
528 			PUSHBYTE(B);
529 			PUSHBYTE(A);
530 			PUSHBYTE(CC);
531 			konami.extra_cycles += 19;	/* subtract +19 cycles next time */
532 		}
533 		CC |= CC_IF | CC_II;			/* inhibit FIRQ and IRQ */
534 		PCD = RM16(0xfffc);
535 		change_pc16(PC);					/* TS 971002 */
536 	}
537 	else if (irqline < 2)
538 	{
539     log_cb(RETRO_LOG_DEBUG, LOGPRE "KONAMI#%d set_irq_line %d, %d\n", cpu_getactivecpu(), irqline, state);
540 		konami.irq_state[irqline] = state;
541 		if (state == CLEAR_LINE) return;
542 		CHECK_IRQ_LINES;
543 	}
544 }
545 
546 /****************************************************************************
547  * Set IRQ vector callback
548  ****************************************************************************/
konami_set_irq_callback(int (* callback)(int irqline))549 void konami_set_irq_callback(int (*callback)(int irqline))
550 {
551 	konami.irq_callback = callback;
552 }
553 #if 0
554 /****************************************************************************
555  * Save CPU state
556  ****************************************************************************/
557 static void state_save(void *file, const char *module)
558 {
559 	int cpu = cpu_getactivecpu();
560 	state_save_UINT16(file, module, cpu, "PC", &PC, 1);
561 	state_save_UINT16(file, module, cpu, "U", &U, 1);
562 	state_save_UINT16(file, module, cpu, "S", &S, 1);
563 	state_save_UINT16(file, module, cpu, "X", &X, 1);
564 	state_save_UINT16(file, module, cpu, "Y", &Y, 1);
565 	state_save_UINT8(file, module, cpu, "DP", &DP, 1);
566 	state_save_UINT8(file, module, cpu, "CC", &CC, 1);
567 	state_save_UINT8(file, module, cpu, "INT", &konami.int_state, 1);
568 	state_save_UINT8(file, module, cpu, "NMI", &konami.nmi_state, 1);
569 	state_save_UINT8(file, module, cpu, "IRQ", &konami.irq_state[0], 1);
570 	state_save_UINT8(file, module, cpu, "FIRQ", &konami.irq_state[1], 1);
571 }
572 
573 /****************************************************************************
574  * Load CPU state
575  ****************************************************************************/
576 static void state_load(void *file, const char *module)
577 {
578 	int cpu = cpu_getactivecpu();
579 	state_load_UINT16(file, module, cpu, "PC", &PC, 1);
580 	state_load_UINT16(file, module, cpu, "U", &U, 1);
581 	state_load_UINT16(file, module, cpu, "S", &S, 1);
582 	state_load_UINT16(file, module, cpu, "X", &X, 1);
583 	state_load_UINT16(file, module, cpu, "Y", &Y, 1);
584 	state_load_UINT8(file, module, cpu, "DP", &DP, 1);
585 	state_load_UINT8(file, module, cpu, "CC", &CC, 1);
586 	state_load_UINT8(file, module, cpu, "INT", &konami.int_state, 1);
587 	state_load_UINT8(file, module, cpu, "NMI", &konami.nmi_state, 1);
588 	state_load_UINT8(file, module, cpu, "IRQ", &konami.irq_state[0], 1);
589 	state_load_UINT8(file, module, cpu, "FIRQ", &konami.irq_state[1], 1);
590 }
591 
592 void konami_state_save(void *file) { state_save(file, "konami"); }
593 void konami_state_load(void *file) { state_load(file, "konami"); }
594 #endif
595 /****************************************************************************
596  * Return a formatted string for a register
597  ****************************************************************************/
konami_info(void * context,int regnum)598 const char *konami_info(void *context, int regnum)
599 {
600 	static char buffer[16][47+1];
601 	static int which = 0;
602 	konami_Regs *r = context;
603 
604 	which = (which+1) % 16;
605     buffer[which][0] = '\0';
606 	if( !context )
607 		r = &konami;
608 
609 	switch( regnum )
610 	{
611 		case CPU_INFO_NAME: return "KONAMI";
612 		case CPU_INFO_FAMILY: return "KONAMI 5000x";
613 		case CPU_INFO_VERSION: return "1.0";
614 		case CPU_INFO_FILE: return __FILE__;
615 		case CPU_INFO_CREDITS: return "Copyright (C) The MAME Team 1999";
616 		case CPU_INFO_REG_LAYOUT: return (const char*)konami_reg_layout;
617 		case CPU_INFO_WIN_LAYOUT: return (const char*)konami_win_layout;
618 
619 		case CPU_INFO_FLAGS:
620 			sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
621 				r->cc & 0x80 ? 'E':'.',
622 				r->cc & 0x40 ? 'F':'.',
623                 r->cc & 0x20 ? 'H':'.',
624                 r->cc & 0x10 ? 'I':'.',
625                 r->cc & 0x08 ? 'N':'.',
626                 r->cc & 0x04 ? 'Z':'.',
627                 r->cc & 0x02 ? 'V':'.',
628                 r->cc & 0x01 ? 'C':'.');
629             break;
630 		case CPU_INFO_REG+KONAMI_PC: sprintf(buffer[which], "PC:%04X", r->pc.w.l); break;
631 		case CPU_INFO_REG+KONAMI_S: sprintf(buffer[which], "S:%04X", r->s.w.l); break;
632 		case CPU_INFO_REG+KONAMI_CC: sprintf(buffer[which], "CC:%02X", r->cc); break;
633 		case CPU_INFO_REG+KONAMI_U: sprintf(buffer[which], "U:%04X", r->u.w.l); break;
634 		case CPU_INFO_REG+KONAMI_A: sprintf(buffer[which], "A:%02X", r->d.b.h); break;
635 		case CPU_INFO_REG+KONAMI_B: sprintf(buffer[which], "B:%02X", r->d.b.l); break;
636 		case CPU_INFO_REG+KONAMI_X: sprintf(buffer[which], "X:%04X", r->x.w.l); break;
637 		case CPU_INFO_REG+KONAMI_Y: sprintf(buffer[which], "Y:%04X", r->y.w.l); break;
638 		case CPU_INFO_REG+KONAMI_DP: sprintf(buffer[which], "DP:%02X", r->dp.b.h); break;
639 		case CPU_INFO_REG+KONAMI_NMI_STATE: sprintf(buffer[which], "NMI:%X", r->nmi_state); break;
640 		case CPU_INFO_REG+KONAMI_IRQ_STATE: sprintf(buffer[which], "IRQ:%X", r->irq_state[KONAMI_IRQ_LINE]); break;
641 		case CPU_INFO_REG+KONAMI_FIRQ_STATE: sprintf(buffer[which], "FIRQ:%X", r->irq_state[KONAMI_FIRQ_LINE]); break;
642 	}
643 	return buffer[which];
644 }
645 
konami_dasm(char * buffer,unsigned pc)646 unsigned konami_dasm(char *buffer, unsigned pc)
647 {
648 #ifdef MAME_DEBUG
649     return Dasmknmi(buffer,pc);
650 #else
651 	sprintf( buffer, "$%02X", cpu_readop(pc) );
652 	return 1;
653 #endif
654 }
655 
656 /* includes the static function prototypes and the master opcode table */
657 #include "konamtbl.c"
658 
659 /* includes the actual opcode implementations */
660 #include "konamops.c"
661 
662 /* execute instructions on this CPU until icount expires */
konami_execute(int cycles)663 int konami_execute(int cycles)
664 {
665 	konami_ICount = cycles - konami.extra_cycles;
666 	konami.extra_cycles = 0;
667 
668 	if( konami.int_state & (KONAMI_CWAI | KONAMI_SYNC) )
669 	{
670 		konami_ICount = 0;
671 	}
672 	else
673 	{
674 		do
675 		{
676 			pPPC = pPC;
677 
678 			CALL_MAME_DEBUG;
679 
680 			konami.ireg = ROP(PCD);
681 			PC++;
682 
683             (*konami_main[konami.ireg])();
684 
685             konami_ICount -= cycles1[konami.ireg];
686 
687         } while( konami_ICount > 0 );
688 
689         konami_ICount -= konami.extra_cycles;
690 		konami.extra_cycles = 0;
691     }
692 
693 	return cycles - konami_ICount;
694 }
695