#pragma message ( "including singlecpu.cc" );
/*****************************************************************************/
/*                                                                           */
/*   Function    : f6809Tick()                                               */
/*                                                                           */
/*   Author      : K.W / C.S.                                                */
/*                                                                           */
/*   Description : This function runs one cycle of CPU time emulation.       */
/*                                                                           */
/*   Accepts     : nothing                                                   */
/*                                                                           */
/*   Returns     : nothing                                                   */
/*                                                                           */
/*****************************************************************************/

{
 /***********************/
 /* Autodecrement count */
 /***********************/
/*
  if (enable_event==3)
  {
   printf("\n-----");
   printf("\nPC:%04X",tsCPURegisters.tPC);
   printf("\nTick:%i",lwGblSystemTickTotal);
  }
  if (enable_event==2)
  if ((tsCPURegisters.tPC==0xf344)||(tsCPURegisters.tPC==0xF349))
  {
   printf("\n-----");
   printf("\nPC:%04X",tsCPURegisters.tPC);
   printf("\nTick:%i",lwGblSystemTickTotal);
   printf("\nNow enable_event=3");
   enable_event=3;
  }
  if (enable_event==1)
  {
   T_SINT x,y;
   if (tsCPURegisters.tPC==0xF2FC)
   {
     printf("\n-----");
     printf("\nPC:%04X",tsCPURegisters.tPC);
     printf("\nTick:%i",lwGblSystemTickTotal);
     enable_event=2;
     x=(signed int)tsCPURegisters.uABD.sAB.tB;
     y=(signed int)tsCPURegisters.uABD.sAB.tA;
     if (x>127) x-=256;
     if (y>127) y-=256;
     printf("\nX supposed: x=%03i y=%03i",x,y);
   }
  }
*/
 if (!iCount)
 {
  /*****************************************/
  /* Switch on the status of the processor */
  /*****************************************/
  switch(i6809status)
  {
   case CPU_FETCH:
   {
#ifndef DEBUG_MSG
    T_PUWORD hpoint;
#endif
    /**********************************************/
    /* Print Instruction disassembly within debug */
    /**********************************************/

/*
      if (enable_event>1)
      {
       printf("\nCycle Count:%i",2+cycle_count[*((T_PUWORD)(atSystemImage+tsCPURegisters.tPC))]);
    {
     T_UWORD    wUBYTECount,wAddress,wLoop;
     T_CHAR    acTmp[STRING_LENGTH];
     T_CHAR    acDisString[STRING_LENGTH];
     T_CHAR    acLine[STRING_LENGTH];
     printf("\n");
     printf("\nf6809Tick() - x   0x%04x    y   0x%04x    d   0x%04x (a=0x%02x  b=0x%02x)",tsCPURegisters.tX,tsCPURegisters.tY,
     tsCPURegisters.uABD.tD,tsCPURegisters.uABD.sAB.tA,tsCPURegisters.uABD.sAB.tB);
     printf("\nf6809Tick() - usp 0x%04x    hsp 0x%04x    dp  0x%02x",tsCPURegisters.tUSP,tsCPURegisters.tHSP,tsCPURegisters.tDP);
     printf("\nf6809Tick() - pc  0x%04x    cc  0x%02x (c=%d v=%d z=%d n=%d)",tsCPURegisters.tPC,tsCPURegisters.uCC.tCC,
     tsCPURegisters.uCC.sCC.bC,tsCPURegisters.uCC.sCC.bV,tsCPURegisters.uCC.sCC.bZ,tsCPURegisters.uCC.sCC.bN);
     printf("\nf6809Tick()");

     wAddress=f6809Disassemble(tsCPURegisters.tPC,acDisString);
     wUBYTECount=wAddress-tsCPURegisters.tPC;
     sprintf(acLine,"%04x  ",tsCPURegisters.tPC);

     for (wLoop=0;wLoop<wUBYTECount;wLoop++)
     {
      sprintf(acTmp,"%02x ",f6809AddressRead(tsCPURegisters.tPC+wLoop));
      strcat(acLine,acTmp);
     }
     for(wLoop=wUBYTECount;wLoop<4;wLoop++)
     {
      strcat(acLine,"   ");
     }
     strcat(acLine,"  ");
     strcat(acLine,acDisString);
     printf("\nf6809Tick() - %s",acLine);
     printf("\nf6809Tick()");
    }
}

*/








#ifdef DEBUG_MSG
    if(tGblDebugLevel==LOW)
    {
     T_UWORD    wUBYTECount,wAddress,wLoop;
     T_CHAR    acTmp[STRING_LENGTH];
     T_CHAR    acDisString[STRING_LENGTH];
     T_CHAR    acLine[STRING_LENGTH];
     fDebug(LOW,(""));
     fDebug(LOW,("f6809Tick() - x   0x%04x    y   0x%04x    d   0x%04x (a=0x%02x  b=0x%02x)",tsCPURegisters.tX,tsCPURegisters.tY,tsCPURegisters.uABD.tD,
     tsCPURegisters.uABD.sAB.tA,tsCPURegisters.uABD.sAB.tB));
     fDebug(LOW,("f6809Tick() - usp 0x%04x    hsp 0x%04x    dp  0x%02x",tsCPURegisters.tUSP,tsCPURegisters.tHSP,tsCPURegisters.tDP));
     fDebug(LOW,("f6809Tick() - pc  0x%04x    cc  0x%02x (c=%d v=%d z=%d n=%d)",tsCPURegisters.tPC,tsCPURegisters.uCC.tCC,tsCPURegisters.uCC.sCC.bC,
     tsCPURegisters.uCC.sCC.bV,tsCPURegisters.uCC.sCC.bZ,tsCPURegisters.uCC.sCC.bN));
     fDebug(LOW,("f6809Tick()"));

     wAddress=f6809Disassemble(tsCPURegisters.tPC,acDisString);
     wUBYTECount=wAddress-tsCPURegisters.tPC;
     sprintf(acLine,"%04x  ",tsCPURegisters.tPC);

     for (wLoop=0;wLoop<wUBYTECount;wLoop++)
     {
      sprintf(acTmp,"%02x ",f6809AddressRead(tsCPURegisters.tPC+wLoop));
      strcat(acLine,acTmp);
     }
     for(wLoop=wUBYTECount;wLoop<4;wLoop++)
     {
      strcat(acLine,"   ");
     }
     strcat(acLine,"  ");
     strcat(acLine,acDisString);
     fDebug(LOW,("f6809Tick() - %s",acLine));
     fDebug(LOW,("f6809Tick()"));
    }
#endif
    /***********************************************************/
    /* iBPTriggered is used as a state toggle, breakpoints     */
    /* are only enabled if they haven't been triggered         */
    /* on the next trip thru after trigger, the BPTrigger will */
    /* be cleared and we'll go into CPU_DECODE                 */
    /***********************************************************/
#ifdef DEBUG_MON
    if (iBreakpointEnable && iBreakpoint==tsCPURegisters.tPC && !iBPTriggered)
    {
     if (iSkipCount>0)
     {
      iSkipCount--;
     }
     else
     {
//      bGblDebugMonitorEnable=T_TRUE;
      bGblPauseMode=T_TRUE;
      vector_undraw();
      vector_refresh();
      vectrex_update->frequency=1;
      if (bGblDebugMonitorEnable!=T_TRUE)
      if (open_monitor_window()==T_TRUE)
      {
       bGblDebugMonitorEnable=T_TRUE;
       if (bGblGUIEnable==T_FALSE)
       {
        WINDOW_LISTEN_ELEMENT *MonitorWin=get_window(MonitorWinId);
        hide_raw_window(MonitorWin);
        back_save(FORCED_SAVE);
        show_all_windows();
       }
       bGblGUIEnable=T_TRUE;
       set_functions();
       reset_state=T_FALSE;
       wGblQuitFlag=EMU_RESTART;
      }
      iBPTriggered=T_TRUE;
      break;
     }
    }
    else
    {
     iBPTriggered=T_FALSE;
    }
    iLastAddress=tsCPURegisters.tPC;
#endif
    /***************************/
    /* Infernal debugging line */
    /***************************/
/*
    if ((tsCPURegisters.tPC&0xfff0)==0xf410 && tsCPURegisters.tX&0xff00!=0xc800 && tsCPURegisters.tX&0xe000!=0xe000)
    {
//     bGblDebugMonitorEnable=T_TRUE;
      bGblPauseMode=T_TRUE;
      vector_undraw();
      vector_refresh();
      vectrex_update->frequency=1;
      if (bGblDebugMonitorEnable!=T_TRUE)
      if (open_monitor_window()==T_TRUE)
      {
       bGblDebugMonitorEnable=T_TRUE;
       if (bGblGUIEnable==T_FALSE)
       {
        WINDOW_LISTEN_ELEMENT *MonitorWin=get_window(MonitorWinId);
        hide_raw_window(MonitorWin);
        back_save(FORCED_SAVE);
        show_all_windows();
       }
       bGblGUIEnable=T_TRUE;
       set_functions();
       reset_state=T_FALSE;
       wGblQuitFlag=EMU_RESTART;
      }
    }
*/
    /**********************************************************/
    /* Check interrupt status ignore NMI as it is unconnected */
    /**********************************************************/
    if (tsCPURegisters.tIRQFlag && !tsCPURegisters.uCC.sCC.bI)
    {
     fDebug(HIGH,("f6809Tick() - IRQ Detected <PC=%04x>",tsCPURegisters.tPC));
     tsCPURegisters.tIRQFlag=0;
     iCount=f6809IRQ();
     tsCPURegisters.tPC=(f6809FastAddressRead(0xfff8)<<8)+f6809FastAddressRead(0xfff9);
     break;
    }
    else if (tsCPURegisters.tFIRQFlag && !tsCPURegisters.uCC.sCC.bF)
    {
     fDebug(HIGH,("f6809Tick() - FIRQ Detected <PC=%04x>",tsCPURegisters.tPC));
     tsCPURegisters.tFIRQFlag=0;
     iCount=f6809FIRQ();
     tsCPURegisters.tPC=(f6809FastAddressRead(0xfff6)<<8)+f6809FastAddressRead(0xfff7);
     break;
    }
    else
    {
#ifndef DEBUG_MSG
     iCount=cycle_count[*(hpoint=(T_PUWORD)(atSystemImage+(tsCPURegisters.tPC++)))];
#endif
#ifdef DEBUG_MSG
     if ((iCount=cycle_count[*((T_UWORD*)(atSystemImage+tsCPURegisters.tPC))])==-1)
     {
      fDebug(VERROR,("f6809Tick() - Bad instruction decoded #$%02x",iInstruction));
      i6809status=CPU_EXCEPTION;
      iCount=0;
      break;
     }
     else
     {
      fDebug(LOW,("f6809Tick() - FETCH CYCLE - Addr $%04x,  OpCode #$%02x, %d cycles before decode",iLastAddress,iInstruction,iCount));
     }
#endif
#ifndef DEBUG_MSG
     iInstruction=*((T_PUCHAR)hpoint);
#endif
#ifdef DEBUG_MSG
     iInstruction=(T_UWORD)f6809FastAddressRead(tsCPURegisters.tPC++);
#endif
     i6809status=CPU_DECODE;
     break;
    }
    break;
   }
   case CPU_DECODE:
   {
    i6809status=(apfExecuteInstruction[iInstruction])();
    fDebug(LOW,("f6809Tick() - DECODE CYCLE- Ret  #$%02x",i6809status));
    break;
   }
   case CPU_HALT:
   {
    f6809Reset();
    i6809status=CPU_WAIT;
    break;
   }
   case CPU_EXCEPTION:
   {
    fDebug(VERROR,("f6809Tick() - Exception generated by instruction #$%02x at address $%04x",iInstruction,iLastAddress));
    i6809status=CPU_WAIT;
#ifdef DEBUG_MON
//    bGblDebugMonitorEnable=T_TRUE;
      bGblPauseMode=T_TRUE;
      vector_undraw();
      vector_refresh();
      vectrex_update->frequency=1;
      if (bGblDebugMonitorEnable!=T_TRUE)
      if (open_monitor_window()==T_TRUE)
      {
       bGblDebugMonitorEnable=T_TRUE;
       if (bGblGUIEnable==T_FALSE)
       {
        WINDOW_LISTEN_ELEMENT *MonitorWin=get_window(MonitorWinId);
        hide_raw_window(MonitorWin);
        back_save(FORCED_SAVE);
        show_all_windows();
       }
       bGblGUIEnable=T_TRUE;
       set_functions();
       reset_state=T_FALSE;
       wGblQuitFlag=EMU_RESTART;
      }
#endif
    break;
   }
   case CPU_CWAI:
   {
    /********************************************************/
    /* CWAI is handled differently as the stack has already */
    /* been pushed                                          */
    /********************************************************/
    if (tsCPURegisters.tIRQFlag && !tsCPURegisters.uCC.sCC.bI)
    {
     tsCPURegisters.tIRQFlag=T_FALSE;
     tsCPURegisters.uCC.sCC.bI=1;
     tsCPURegisters.uCC.sCC.bF=1;
     tsCPURegisters.tPC=(f6809FastAddressRead(0xfff8)<<8)+f6809FastAddressRead(0xfff9);
     i6809status=CPU_FETCH;
     fDebug(HIGH,("f6809Tick() - IRQ Detected, cwai released to addr %04x",tsCPURegisters.tPC));
     break;
    }
    else if(tsCPURegisters.tFIRQFlag && !tsCPURegisters.uCC.sCC.bF)
    {
     tsCPURegisters.tFIRQFlag=T_FALSE;
     tsCPURegisters.uCC.sCC.bI=1;
     tsCPURegisters.uCC.sCC.bF=1;
     tsCPURegisters.tPC=(f6809FastAddressRead(0xfff6)<<8)+f6809FastAddressRead(0xfff7);
     i6809status=CPU_FETCH;
     fDebug(HIGH,("f6809Tick() - FIRQ Detected, cwai released to addr %04x",tsCPURegisters.tPC));
     break;
    }
    else if(tsCPURegisters.uCC.sCC.bI & tsCPURegisters.uCC.sCC.bI)
    {
     fopen_monitor_debug_pause();
#define _fDebug(level,body) ((bGblDebugEnable==T_TRUE && level>=tGblDebugLevel)?(tGblDebugMsgLevel=level),(fDebugXX body):0)
     _fDebug(HIGH,("f6809SingleTick() CWAI - CPU permanently halted wait for NMI at addr $%04x",tsCPURegisters.tPC));
#undef _fDebug
    }
    break;
   }
   case CPU_SYNC:
   {
    /******************************************************************/
    /* Leave the interrupt handler in CPU_FETCH to handle the IRQ now */
    /******************************************************************/
    if (tsCPURegisters.tIRQFlag)
    {
     fDebug(HIGH,("f6809Tick() - IRQ Detected, sync released to addr %04x",tsCPURegisters.tPC));
     i6809status=CPU_FETCH;
    }
    if (tsCPURegisters.tFIRQFlag)
    {
     fDebug(HIGH,("f6809Tick() - FIRQ Detected, sync released to addr %04x",tsCPURegisters.tPC));
     i6809status=CPU_FETCH;
    }
    break;
   }
   case CPU_WAIT:
   {
    fopen_monitor_debug_pause();
#define _fDebug(level,body) ((bGblDebugEnable==T_TRUE && level>=tGblDebugLevel)?(tGblDebugMsgLevel=level),(fDebugXX body):0)
    _fDebug(HIGH,("CPU ERROR - Exception generated, emulator will now reset"));
#undef _fDebug
    bGblStatsValid=T_FALSE;
    fSequencerReboot(0);
    break;
   }
   default:
   {
    /****************************************************/
    /* Default case is used to add further delay cycles */
    /* 00 = Fetch, all other codes are 0xf8 onwards     */
    /****************************************************/
    i6809status--;
    break;
   }
  }
 }
 else
 {
  iCount--;
 }
}
