/** VGB: portable GameBoy emulator ***************************/
/**                                                         **/
/**                          Lame.h                         **/
/**                                                         **/
/** This file is compiled when LAME id #defined. It         **/
/** contains simplified Z80 engine.                         **/
/**                                                         **/
/** Copyright (C) Marat Fayzullin 1994,1995                 **/
/**     You are not allowed to distribute this software     **/
/**     commercially. Please, notify me, if you make any    **/   
/**     changes to this file.                               **/
/*************************************************************/

void CodesCB(void)
{
  register byte I;

  switch(*(Addr+(R.PC.W++)))
  {
#include "CodesCB.h"
    default:
      if(TrapBadOps)
        printf("Unrecognized CB instruction at PC=%hX\n",R.PC.W-2);
  }
}

void CodesED(void)
{
  register byte I;
  register pair J;

  switch(*(Addr+(R.PC.W++)))
  {
#include "CodesED.h"
    default:
      if(TrapBadOps)
        printf
        (
          "Unrecognized instruction: ED %X at PC=%hX\n",
          *(Addr+R.PC.W-1),R.PC.W-2
        );
  }
}

word Z80(register byte *A,reg Regs)
{
  register byte I;
  register pair J;

  R=Regs;Addr=A;

#ifdef INTERRUPTS
  Cnt=IPeriod;
#endif
  
  for(CPURunning=1;CPURunning;)
  {
    LCDSTAT=(LCDSTAT&0xFC)|((Cnt>>5)&0x03);

    switch(*(Addr+(R.PC.W++)))
    {
#include "Codes.h"
      case PFX_CB: CodesCB();break;
      case PFX_ED: CodesED();break;
      case 0x10:  
      case HALT: 
#ifdef INTERRUPTS
        if(Cnt) R.PC.W--; else R.IFF|=0x01;
#else   
        printf("CPU HALTed and stuck at PC=%hX\n",--R.PC.W);
        CPURunning=0;
#endif
        break;
      default:
        if(TrapBadOps)
          printf("Unrecognized instruction at PC=%hX\n",R.PC.W-1);
    }
 
#ifdef INTERRUPTS
    if(!Cnt--) 
    {
      Cnt=IPeriod;
      if(IntSync) IFlag=1;
    }
    if(IFlag)
    {
      IFlag=0;J.W=Interrupt();
      if((J.W!=0xFFFF)&&(R.IFF&0x01))
      { M_PUSH(PC);R.PC.W=R.IFF&0x04? ((word)R.I<<8)+0xFF:J.W; }
    }  
#endif

#ifdef DEBUG
    if(R.PC.W==Trap) Trace=1;  /*** Turn tracing on if trapped ***/
    if(Trace) Z80_Debug(Addr,R);   /*** Call single-step debugger  ***/
#endif

  }
  return(R.PC.W);
}
