Viewing File: <root>/src/emu/cpu/konami/konami.c

    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      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 "emu.h"
   38  #include "debugger.h"
   39  #include "konami.h"
   40  
   41  #define VERBOSE 0
   42  
   43  #define LOG(x)  do { if (VERBOSE) logerror x; } while (0)
   44  
   45  /* Konami Registers */
   46  struct konami_state
   47  {
   48      PAIR    pc;         /* Program counter */
   49      PAIR    ppc;        /* Previous program counter */
   50      PAIR    d;          /* Accumulator a and b */
   51      PAIR    dp;         /* Direct Page register (page in MSB) */
   52      PAIR    u, s;       /* Stack pointers */
   53      PAIR    x, y;       /* Index registers */
   54      PAIR    ea;
   55      UINT8   cc;
   56      UINT8   ireg;
   57      UINT8   irq_state[2];
   58      device_irq_acknowledge_callback irq_callback;
   59      UINT8   int_state;  /* SYNC and CWAI flags */
   60      UINT8   nmi_state;
   61      UINT8   nmi_pending;
   62      int     icount;
   63      legacy_cpu_device *device;
   64      address_space *program;
   65      direct_read_data *direct;
   66      konami_set_lines_func setlines_callback;
   67  };
   68  
   69  INLINE konami_state *get_safe_token(device_t *device)
   70  {
   71      assert(device != NULL);
   72      assert(device->type() == KONAMI);
   73      return (konami_state *)downcast<legacy_cpu_device *>(device)->token();
   74  }
   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  #define pPPC    cpustate->ppc
   88  #define pPC     cpustate->pc
   89  #define pU      cpustate->u
   90  #define pS      cpustate->s
   91  #define pX      cpustate->x
   92  #define pY      cpustate->y
   93  #define pD      cpustate->d
   94  
   95  #define PPC     cpustate->ppc.w.l
   96  #define PC      cpustate->pc.w.l
   97  #define PCD     cpustate->pc.d
   98  #define U       cpustate->u.w.l
   99  #define UD      cpustate->u.d
  100  #define S       cpustate->s.w.l
  101  #define SD      cpustate->s.d
  102  #define X       cpustate->x.w.l
  103  #define XD      cpustate->x.d
  104  #define Y       cpustate->y.w.l
  105  #define YD      cpustate->y.d
  106  #define D       cpustate->d.w.l
  107  #define A       cpustate->d.b.h
  108  #define B       cpustate->d.b.l
  109  #define DP      cpustate->dp.b.h
  110  #define DPD     cpustate->dp.d
  111  #define CC      cpustate->cc
  112  
  113  #define EAB     cpustate->ea.b.l
  114  #define EA      cpustate->ea.w.l
  115  #define EAD     cpustate->ea.d
  116  
  117  #define KONAMI_CWAI     8   /* set when CWAI is waiting for an interrupt */
  118  #define KONAMI_SYNC     16  /* set when SYNC is waiting for an interrupt */
  119  #define KONAMI_LDS      32  /* set when LDS occurred at least once */
  120  
  121  #define RM(cs,Addr)             (cs)->program->read_byte(Addr)
  122  #define WM(cs,Addr,Value)       (cs)->program->write_byte(Addr,Value)
  123  #define ROP(cs,Addr)            (cs)->direct->read_decrypted_byte(Addr)
  124  #define ROP_ARG(cs,Addr)        (cs)->direct->read_raw_byte(Addr)
  125  
  126  #define SIGNED(a)   (UINT16)(INT16)(INT8)(a)
  127  
  128  /* macros to access memory */
  129  #define IMMBYTE(cs,b)   { b = ROP_ARG(cs,PCD); PC++; }
  130  #define IMMWORD(cs,w)   { w.d = (ROP_ARG(cs,PCD)<<8) | ROP_ARG(cs,PCD+1); PC += 2; }
  131  
  132  #define PUSHBYTE(cs,b) --S; WM(cs,SD,b)
  133  #define PUSHWORD(cs,w) --S; WM(cs,SD,w.b.l); --S; WM(cs,SD,w.b.h)
  134  #define PULLBYTE(cs,b) b=RM(cs,SD); S++
  135  #define PULLWORD(cs,w) w=RM(cs,SD)<<8; S++; w|=RM(cs,SD); S++
  136  
  137  #define PSHUBYTE(cs,b) --U; WM(cs,UD,b);
  138  #define PSHUWORD(cs,w) --U; WM(cs,UD,w.b.l); --U; WM(cs,UD,w.b.h)
  139  #define PULUBYTE(cs,b) b=RM(cs,UD); U++
  140  #define PULUWORD(cs,w) w=RM(cs,UD)<<8; U++; w|=RM(cs,UD); U++
  141  
  142  #define CLR_HNZVC   CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
  143  #define CLR_NZV     CC&=~(CC_N|CC_Z|CC_V)
  144  #define CLR_NZ      CC&=~(CC_N|CC_Z)
  145  #define CLR_HNZC    CC&=~(CC_H|CC_N|CC_Z|CC_C)
  146  #define CLR_NZVC    CC&=~(CC_N|CC_Z|CC_V|CC_C)
  147  #define CLR_Z       CC&=~(CC_Z)
  148  #define CLR_NZC     CC&=~(CC_N|CC_Z|CC_C)
  149  #define CLR_ZC      CC&=~(CC_Z|CC_C)
  150  
  151  /* macros for CC -- CC bits affected should be reset before calling */
  152  #define SET_Z(a)        if(!a)SEZ
  153  #define SET_Z8(a)       SET_Z((UINT8)a)
  154  #define SET_Z16(a)      SET_Z((UINT16)a)
  155  #define SET_N8(a)       CC|=((a&0x80)>>4)
  156  #define SET_N16(a)      CC|=((a&0x8000)>>12)
  157  #define SET_H(a,b,r)    CC|=(((a^b^r)&0x10)<<1)
  158  #define SET_C8(a)       CC|=((a&0x100)>>8)
  159  #define SET_C16(a)      CC|=((a&0x10000)>>16)
  160  #define SET_V8(a,b,r)   CC|=(((a^b^r^(r>>1))&0x80)>>6)
  161  #define SET_V16(a,b,r)  CC|=(((a^b^r^(r>>1))&0x8000)>>14)
  162  
  163  static const UINT8 flags8i[256]=     /* increment */
  164  {
  165  CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  166  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  167  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  168  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  169  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  170  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  171  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  172  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  173  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,
  174  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,
  175  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,
  176  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,
  177  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,
  178  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,
  179  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,
  180  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
  181  };
  182  static const UINT8 flags8d[256]= /* decrement */
  183  {
  184  CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  185  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  186  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  187  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  188  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  189  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  190  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  191  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V,
  192  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,
  193  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,
  194  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,
  195  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,
  196  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,
  197  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,
  198  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,
  199  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
  200  };
  201  #define SET_FLAGS8I(a)      {CC|=flags8i[(a)&0xff];}
  202  #define SET_FLAGS8D(a)      {CC|=flags8d[(a)&0xff];}
  203  
  204  /* combos */
  205  #define SET_NZ8(a)          {SET_N8(a);SET_Z(a);}
  206  #define SET_NZ16(a)         {SET_N16(a);SET_Z(a);}
  207  #define SET_FLAGS8(a,b,r)   {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
  208  #define SET_FLAGS16(a,b,r)  {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
  209  
  210  /* macros for addressing modes (postbytes have their own code) */
  211  #define DIRECT(cs)  EAD = DPD; IMMBYTE(cs,EAB)
  212  #define IMM8(cs)    EAD = PCD; PC++
  213  #define IMM16(cs)   EAD = PCD; PC+=2
  214  #define EXTENDED(cs) IMMWORD(cs,(cs)->ea)
  215  
  216  /* macros to set status flags */
  217  #if defined(SEC)
  218  #undef SEC
  219  #endif
  220  #define SEC CC|=CC_C
  221  #define CLC CC&=~CC_C
  222  #define SEZ CC|=CC_Z
  223  #define CLZ CC&=~CC_Z
  224  #define SEN CC|=CC_N
  225  #define CLN CC&=~CC_N
  226  #define SEV CC|=CC_V
  227  #define CLV CC&=~CC_V
  228  #define SEH CC|=CC_H
  229  #define CLH CC&=~CC_H
  230  
  231  /* macros for convenience */
  232  #define DIRBYTE(cs,b) DIRECT(cs); b=RM(cs,EAD)
  233  #define DIRWORD(cs,w) DIRECT(cs); w.d=RM16(cs,EAD)
  234  #define EXTBYTE(cs,b) EXTENDED(cs); b=RM(cs,EAD)
  235  #define EXTWORD(cs,w) EXTENDED(cs); w.d=RM16(cs,EAD)
  236  
  237  /* macros for branch instructions */
  238  #define BRANCH(cs,f) {                  \
  239      UINT8 t;                            \
  240      IMMBYTE(cs,t);                      \
  241      if( f )                             \
  242      {                                   \
  243          PC += SIGNED(t);                \
  244      }                                   \
  245  }
  246  
  247  #define LBRANCH(cs,f) {                 \
  248      PAIR t;                             \
  249      IMMWORD(cs,t);                      \
  250      if( f )                             \
  251      {                                   \
  252          cpustate->icount -= 1;          \
  253          PC += t.w.l;                    \
  254      }                                   \
  255  }
  256  
  257  #define NXORV  ((CC&CC_N)^((CC&CC_V)<<2))
  258  
  259  /* macros for setting/getting registers in TFR/EXG instructions */
  260  #define GETREG(val,reg)                 \
  261      switch(reg) {                       \
  262      case 0: val = A;    break;          \
  263      case 1: val = B;    break;          \
  264      case 2: val = X;    break;          \
  265      case 3: val = Y;    break;          \
  266      case 4: val = S;    break; /* ? */  \
  267      case 5: val = U;    break;          \
  268      default: val = 0xff; logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
  269      }
  270  
  271  #define SETREG(val,reg)                 \
  272      switch(reg) {                       \
  273      case 0: A = val;    break;          \
  274      case 1: B = val;    break;          \
  275      case 2: X = val;    break;          \
  276      case 3: Y = val;    break;          \
  277      case 4: S = val;    break; /* ? */  \
  278      case 5: U = val;    break;          \
  279      default: logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
  280      }
  281  
  282  /* opcode timings */
  283  static const UINT8 cycles1[] =
  284  {
  285      /*   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
  286      /*0*/  1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5,
  287      /*1*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  288      /*2*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  289      /*3*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 7, 6,
  290      /*4*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
  291      /*5*/  4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 1, 1, 1,
  292      /*6*/  3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
  293      /*7*/  3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
  294      /*8*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
  295      /*9*/  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
  296      /*A*/  2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 2, 1,
  297      /*B*/  3, 2, 2,11,22,11, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3,
  298      /*C*/  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2,
  299      /*D*/  2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  300      /*E*/  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  301      /*F*/  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  302  };
  303  
  304  INLINE UINT32 RM16( konami_state *cpustate, UINT32 Addr )
  305  {
  306      UINT32 result = RM(cpustate, Addr) << 8;
  307      return result | RM(cpustate, (Addr+1)&0xffff);
  308  }
  309  
  310  INLINE void WM16( konami_state *cpustate, UINT32 Addr, PAIR *p )
  311  {
  312      WM(cpustate,  Addr, p->b.h );
  313      WM(cpustate,  (Addr+1)&0xffff, p->b.l );
  314  }
  315  
  316  
  317  static void check_irq_lines(konami_state *cpustate)
  318  {
  319      if (cpustate->nmi_pending && (cpustate->int_state & KONAMI_LDS))
  320      {
  321          cpustate->nmi_pending = FALSE;
  322  
  323          /* state already saved by CWAI? */
  324          if (cpustate->int_state & KONAMI_CWAI)
  325          {
  326              cpustate->int_state &= ~KONAMI_CWAI;
  327              cpustate->icount -= 7;
  328          }
  329          else
  330          {
  331              CC |= CC_E;                 /* save entire state */
  332              PUSHWORD(cpustate, pPC);
  333              PUSHWORD(cpustate, pU);
  334              PUSHWORD(cpustate, pY);
  335              PUSHWORD(cpustate, pX);
  336              PUSHBYTE(cpustate, DP);
  337              PUSHBYTE(cpustate, B);
  338              PUSHBYTE(cpustate, A);
  339              PUSHBYTE(cpustate, CC);
  340              cpustate->icount -= 19;
  341          }
  342          CC |= CC_IF | CC_II;            /* inhibit FIRQ and IRQ */
  343          PCD = RM16(cpustate, 0xfffc);
  344          (void)(*cpustate->irq_callback)(cpustate->device, INPUT_LINE_NMI);
  345      }
  346  
  347      else if (cpustate->irq_state[KONAMI_FIRQ_LINE] !=CLEAR_LINE && !(CC & CC_IF))
  348      {
  349          /* fast IRQ */
  350          /* state already saved by CWAI? */
  351          if (cpustate->int_state & KONAMI_CWAI)
  352          {
  353              cpustate->int_state &= ~KONAMI_CWAI;  /* clear CWAI */
  354              cpustate->icount -= 7;
  355          }
  356          else
  357          {
  358              CC &= ~CC_E;                /* save 'short' state */
  359              PUSHWORD(cpustate, pPC);
  360              PUSHBYTE(cpustate, CC);
  361              cpustate->icount -= 10;
  362          }
  363          CC |= CC_IF | CC_II;            /* inhibit FIRQ and IRQ */
  364          PCD = RM16(cpustate, 0xfff6);
  365          (void)(*cpustate->irq_callback)(cpustate->device, KONAMI_FIRQ_LINE);
  366      }
  367  
  368      else if (cpustate->irq_state[KONAMI_IRQ_LINE] != CLEAR_LINE && !(CC & CC_II))
  369      {
  370          /* standard IRQ */
  371          /* state already saved by CWAI? */
  372          if (cpustate->int_state & KONAMI_CWAI)
  373          {
  374              cpustate->int_state &= ~KONAMI_CWAI;  /* clear CWAI flag */
  375              cpustate->icount -= 7;
  376          }
  377          else
  378          {
  379              CC |= CC_E;                 /* save entire state */
  380              PUSHWORD(cpustate, pPC);
  381              PUSHWORD(cpustate, pU);
  382              PUSHWORD(cpustate, pY);
  383              PUSHWORD(cpustate, pX);
  384              PUSHBYTE(cpustate, DP);
  385              PUSHBYTE(cpustate, B);
  386              PUSHBYTE(cpustate, A);
  387              PUSHBYTE(cpustate, CC);
  388              cpustate->icount -= 19;
  389          }
  390          CC |= CC_II;                    /* inhibit IRQ */
  391          PCD = RM16(cpustate, 0xfff8);
  392          (void)(*cpustate->irq_callback)(cpustate->device, KONAMI_IRQ_LINE);
  393      }
  394  }
  395  
  396  
  397  /****************************************************************************/
  398  /* Reset registers to their initial values                                  */
  399  /****************************************************************************/
  400  static CPU_INIT( konami )
  401  {
  402      konami_state *cpustate = get_safe_token(device);
  403  
  404      cpustate->irq_callback = irqcallback;
  405      cpustate->device = device;
  406      cpustate->program = &device->space(AS_PROGRAM);
  407      cpustate->direct = &cpustate->program->direct();
  408  
  409      device->save_item(NAME(PC));
  410      device->save_item(NAME(U));
  411      device->save_item(NAME(S));
  412      device->save_item(NAME(X));
  413      device->save_item(NAME(Y));
  414      device->save_item(NAME(D));
  415      device->save_item(NAME(DP));
  416      device->save_item(NAME(CC));
  417      device->save_item(NAME(cpustate->int_state));
  418      device->save_item(NAME(cpustate->nmi_state));
  419      device->save_item(NAME(cpustate->nmi_pending));
  420      device->save_item(NAME(cpustate->irq_state[0]));
  421      device->save_item(NAME(cpustate->irq_state[1]));
  422  }
  423  
  424  static CPU_RESET( konami )
  425  {
  426      konami_state *cpustate = get_safe_token(device);
  427  
  428      cpustate->int_state = 0;
  429      cpustate->nmi_state = CLEAR_LINE;
  430      cpustate->nmi_pending = FALSE;
  431      cpustate->irq_state[0] = CLEAR_LINE;
  432      cpustate->irq_state[1] = CLEAR_LINE;
  433  
  434      DPD = 0;            /* Reset direct page register */
  435  
  436      CC |= CC_II;        /* IRQ disabled */
  437      CC |= CC_IF;        /* FIRQ disabled */
  438  
  439      PCD = RM16(cpustate, 0xfffe);
  440  }
  441  
  442  static CPU_EXIT( konami )
  443  {
  444  }
  445  
  446  /* Generate interrupts */
  447  /****************************************************************************
  448   * Set IRQ line state
  449   ****************************************************************************/
  450  static void set_irq_line(konami_state *cpustate, int irqline, int state)
  451  {
  452      if (state != CLEAR_LINE)
  453          cpustate->int_state &= ~KONAMI_SYNC;
  454  
  455      if (irqline == INPUT_LINE_NMI)
  456      {
  457          if (cpustate->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
  458              cpustate->nmi_pending = TRUE;
  459          cpustate->nmi_state = state;
  460      }
  461      else if (irqline < ARRAY_LENGTH(cpustate->irq_state))
  462          cpustate->irq_state[irqline] = state;
  463  }
  464  
  465  /* includes the static function prototypes and the master opcode table */
  466  #include "konamtbl.c"
  467  
  468  /* includes the actual opcode implementations */
  469  #include "konamops.c"
  470  
  471  /* execute instructions on this CPU until icount expires */
  472  static CPU_EXECUTE( konami )
  473  {
  474      konami_state *cpustate = get_safe_token(device);
  475  
  476      check_irq_lines(cpustate);
  477  
  478      if( cpustate->int_state & (KONAMI_CWAI | KONAMI_SYNC) )
  479      {
  480          cpustate->icount = 0;
  481      }
  482      else
  483      {
  484          do
  485          {
  486              UINT8 ireg;
  487  
  488              pPPC = pPC;
  489  
  490              debugger_instruction_hook(device, PCD);
  491  
  492              cpustate->ireg = ireg = ROP(cpustate, PCD);
  493              PC++;
  494  
  495              (*konami_main[ireg])(cpustate);
  496  
  497              cpustate->icount -= cycles1[ireg];
  498  
  499          } while( cpustate->icount > 0 );
  500      }
  501  }
  502  
  503  
  504  void konami_configure_set_lines(device_t *device, konami_set_lines_func func)
  505  {
  506      konami_state *cpustate = get_safe_token(device);
  507      cpustate->setlines_callback = func;
  508  }
  509  
  510  
  511  /**************************************************************************
  512   * Generic set_info
  513   **************************************************************************/
  514  
  515  static CPU_SET_INFO( konami )
  516  {
  517      konami_state *cpustate = get_safe_token(device);
  518      switch (state)
  519      {
  520          /* --- the following bits of info are set as 64-bit signed integers --- */
  521          case CPUINFO_INT_INPUT_STATE + KONAMI_IRQ_LINE: set_irq_line(cpustate, KONAMI_IRQ_LINE, info->i);   break;
  522          case CPUINFO_INT_INPUT_STATE + KONAMI_FIRQ_LINE:set_irq_line(cpustate, KONAMI_FIRQ_LINE, info->i); break;
  523          case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:  set_irq_line(cpustate, INPUT_LINE_NMI, info->i);    break;
  524  
  525          case CPUINFO_INT_PC:
  526          case CPUINFO_INT_REGISTER + KONAMI_PC:          PC = info->i;                           break;
  527          case CPUINFO_INT_SP:
  528          case CPUINFO_INT_REGISTER + KONAMI_S:           S = info->i;                            break;
  529          case CPUINFO_INT_REGISTER + KONAMI_CC:          CC = info->i;                           break;
  530          case CPUINFO_INT_REGISTER + KONAMI_U:           U = info->i;                            break;
  531          case CPUINFO_INT_REGISTER + KONAMI_A:           A = info->i;                            break;
  532          case CPUINFO_INT_REGISTER + KONAMI_B:           B = info->i;                            break;
  533          case CPUINFO_INT_REGISTER + KONAMI_X:           X = info->i;                            break;
  534          case CPUINFO_INT_REGISTER + KONAMI_Y:           Y = info->i;                            break;
  535          case CPUINFO_INT_REGISTER + KONAMI_DP:          DP = info->i;                           break;
  536      }
  537  }
  538  
  539  
  540  
  541  /**************************************************************************
  542   * Generic get_info
  543   **************************************************************************/
  544  
  545  CPU_GET_INFO( konami )
  546  {
  547      konami_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
  548      switch (state)
  549      {
  550          /* --- the following bits of info are returned as 64-bit signed integers --- */
  551          case CPUINFO_INT_CONTEXT_SIZE:                  info->i = sizeof(konami_state);         break;
  552          case CPUINFO_INT_INPUT_LINES:                   info->i = 2;                            break;
  553          case CPUINFO_INT_DEFAULT_IRQ_VECTOR:            info->i = 0;                            break;
  554          case CPUINFO_INT_ENDIANNESS:                    info->i = ENDIANNESS_BIG;               break;
  555          case CPUINFO_INT_CLOCK_MULTIPLIER:              info->i = 1;                            break;
  556          case CPUINFO_INT_CLOCK_DIVIDER:                 info->i = 1;                            break;
  557          case CPUINFO_INT_MIN_INSTRUCTION_BYTES:         info->i = 1;                            break;
  558          case CPUINFO_INT_MAX_INSTRUCTION_BYTES:         info->i = 4;                            break;
  559          case CPUINFO_INT_MIN_CYCLES:                    info->i = 1;                            break;
  560          case CPUINFO_INT_MAX_CYCLES:                    info->i = 13;                           break;
  561  
  562          case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM:    info->i = 8;                    break;
  563          case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16;                  break;
  564          case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0;                   break;
  565          case CPUINFO_INT_DATABUS_WIDTH + AS_DATA:   info->i = 0;                    break;
  566          case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA:   info->i = 0;                    break;
  567          case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA:   info->i = 0;                    break;
  568          case CPUINFO_INT_DATABUS_WIDTH + AS_IO:     info->i = 0;                    break;
  569          case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO:     info->i = 0;                    break;
  570          case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO:     info->i = 0;                    break;
  571  
  572          case CPUINFO_INT_INPUT_STATE + KONAMI_IRQ_LINE: info->i = cpustate->irq_state[KONAMI_IRQ_LINE]; break;
  573          case CPUINFO_INT_INPUT_STATE + KONAMI_FIRQ_LINE:info->i = cpustate->irq_state[KONAMI_FIRQ_LINE]; break;
  574          case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:  info->i = cpustate->nmi_state;              break;
  575  
  576          case CPUINFO_INT_PREVIOUSPC:                    info->i = PPC;                          break;
  577  
  578          case CPUINFO_INT_PC:
  579          case CPUINFO_INT_REGISTER + KONAMI_PC:          info->i = PC;                           break;
  580          case CPUINFO_INT_SP:
  581          case CPUINFO_INT_REGISTER + KONAMI_S:           info->i = S;                            break;
  582          case CPUINFO_INT_REGISTER + KONAMI_CC:          info->i = CC;                           break;
  583          case CPUINFO_INT_REGISTER + KONAMI_U:           info->i = U;                            break;
  584          case CPUINFO_INT_REGISTER + KONAMI_A:           info->i = A;                            break;
  585          case CPUINFO_INT_REGISTER + KONAMI_B:           info->i = B;                            break;
  586          case CPUINFO_INT_REGISTER + KONAMI_X:           info->i = X;                            break;
  587          case CPUINFO_INT_REGISTER + KONAMI_Y:           info->i = Y;                            break;
  588          case CPUINFO_INT_REGISTER + KONAMI_DP:          info->i = DP;                           break;
  589  
  590          /* --- the following bits of info are returned as pointers to data or functions --- */
  591          case CPUINFO_FCT_SET_INFO:                      info->setinfo = CPU_SET_INFO_NAME(konami);      break;
  592          case CPUINFO_FCT_INIT:                          info->init = CPU_INIT_NAME(konami);             break;
  593          case CPUINFO_FCT_RESET:                         info->reset = CPU_RESET_NAME(konami);           break;
  594          case CPUINFO_FCT_EXIT:                          info->exit = CPU_EXIT_NAME(konami);             break;
  595          case CPUINFO_FCT_EXECUTE:                       info->execute = CPU_EXECUTE_NAME(konami);       break;
  596          case CPUINFO_FCT_BURN:                          info->burn = NULL;                              break;
  597          case CPUINFO_FCT_DISASSEMBLE:                   info->disassemble = CPU_DISASSEMBLE_NAME(konami);break;
  598          case CPUINFO_PTR_INSTRUCTION_COUNTER:           info->icount = &cpustate->icount;               break;
  599  
  600          /* --- the following bits of info are returned as NULL-terminated strings --- */
  601          case CPUINFO_STR_NAME:                          strcpy(info->s, "KONAMI");              break;
  602          case CPUINFO_STR_FAMILY:                    strcpy(info->s, "KONAMI 5000x");        break;
  603          case CPUINFO_STR_VERSION:                   strcpy(info->s, "1.0");                 break;
  604          case CPUINFO_STR_SOURCE_FILE:                       strcpy(info->s, __FILE__);              break;
  605          case CPUINFO_STR_CREDITS:                   strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
  606  
  607          case CPUINFO_STR_FLAGS:
  608              sprintf(info->s, "%c%c%c%c%c%c%c%c",
  609                  cpustate->cc & 0x80 ? 'E':'.',
  610                  cpustate->cc & 0x40 ? 'F':'.',
  611                  cpustate->cc & 0x20 ? 'H':'.',
  612                  cpustate->cc & 0x10 ? 'I':'.',
  613                  cpustate->cc & 0x08 ? 'N':'.',
  614                  cpustate->cc & 0x04 ? 'Z':'.',
  615                  cpustate->cc & 0x02 ? 'V':'.',
  616                  cpustate->cc & 0x01 ? 'C':'.');
  617              break;
  618  
  619          case CPUINFO_STR_REGISTER + KONAMI_PC:          sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
  620          case CPUINFO_STR_REGISTER + KONAMI_S:           sprintf(info->s, "S:%04X", cpustate->s.w.l); break;
  621          case CPUINFO_STR_REGISTER + KONAMI_CC:          sprintf(info->s, "CC:%02X", cpustate->cc); break;
  622          case CPUINFO_STR_REGISTER + KONAMI_U:           sprintf(info->s, "U:%04X", cpustate->u.w.l); break;
  623          case CPUINFO_STR_REGISTER + KONAMI_A:           sprintf(info->s, "A:%02X", cpustate->d.b.h); break;
  624          case CPUINFO_STR_REGISTER + KONAMI_B:           sprintf(info->s, "B:%02X", cpustate->d.b.l); break;
  625          case CPUINFO_STR_REGISTER + KONAMI_X:           sprintf(info->s, "X:%04X", cpustate->x.w.l); break;
  626          case CPUINFO_STR_REGISTER + KONAMI_Y:           sprintf(info->s, "Y:%04X", cpustate->y.w.l); break;
  627          case CPUINFO_STR_REGISTER + KONAMI_DP:          sprintf(info->s, "DP:%02X", cpustate->dp.b.h); break;
  628      }
  629  }
  630  
  631  DEFINE_LEGACY_CPU_DEVICE(KONAMI, konami);