////////////////////////////////////////////////////////////////////////////////
// Chip.h -- this file is part of the Emulator Developers Kit
// available at http://ourworld.compuserve.com/homepages/pc64/develop.htm

class Chip : public Object {
protected:

  // function pointers for accessing registers in derived classes
  // note: must be set in the constructor to allow persistence
  const enum { DummyReads = 1 };
  struct Register {
    bpfn bpfnOnRead;   // CPU reads byte
    pfnb pfnbOnWrite;  // CPU writes byte
    int iFlags;        // either 0 or DummyReads if reading clears register
  };
  const Register* pRegisters;
  int iRegisterCount;

  // normal chips act in o2 low phase
  // use CPU as the base class for chips which need to act in o2 high phase
  flag fBusy;
  Chip* pPrevChip;
  Chip* pNextChip;
  pfn pfnOnClock;
  Clock* pClock;

public:

  // constructor
  global Chip() {
    pRegisters = NULL;
    iRegisterCount = 0;
    fBusy = false;
    pPrevChip = NULL;
    pNextChip = NULL;
    pfnOnClock = NULL;
    pClock = NULL;
  }

  // destructor
  global virtual ~Chip() {
    if (IsBusy() && this != (Chip*)pClock) {
      SetIdle();
    }
  }

  // set a new clock
  global virtual void SetClock(Clock& NewClock);

  // get and set function for the next clock cyle
  inline void SetOnClock(pfn pfnNewOnClock) {
    pfnOnClock = pfnNewOnClock;
  }
  inline pfn GetOnClock() {
    return pfnOnClock;
  }

  // preventing the execution of OnClock in idle phases will save time
  // a Chip is linked in after the clock (o2 low phase)
  // a CPU is linked in before the clock (o2 high phase)
  // Chip::SetBusy is virtual because it gets overridden by the CPU class
  global virtual void SetBusy();
  global void SetIdle();
  inline flag IsBusy() {
    return fBusy;
  }
  inline flag IsIdle() {
    return !fBusy;
  }
};
