////////////////////////////////////////////////////////////////////////////////
// NewExtension.cpp -- Template for new PC64Win extensions
// 
// Maps a custom register at $DE00. Set a breakpoint with <F9> at
// NewExtension::ReadDE00() and then press <F5> to compile and run.
// If you enter ?PEEK(53472), Visual C++ will stop at ReadDE00. When
// you continue the execution with <F5>, the C64 will print 123.
//
// In Visual C++ "Tools / Options / Directories", add
//   Include files                = C:\PC64Win\EDK\Include
//
// In Visual C++ "Build / Settings / Debug", set
//   Executable for debug session = ..\PC64Win.exe
//   Working Directory            = ..
//   Program arguments            = -extension "NewExtension.dll"

#include <EDK.h>


class NewExtension : public Object {

  C64* pC64;
  CPU6510C64* pCPU;
  byte* pbIO;
  byte bTrapDE00;

public:

  // constructor
  NewExtension() {
    pC64 = NULL;
    pCPU = NULL;
    pbIO = NULL;
    bTrapDE00 = 0;
  }

  // destructor
  virtual ~NewExtension() {
    if (bTrapDE00 != 0) {
      pCPU->ClearTrap(pbIO + 0x0E00);
      pCPU->FreeTrap(bTrapDE00);
      bTrapDE00 = 0;
    }
  }

  // initialisation
  virtual void DoInit();

  // access functions
  byte ReadDE00();
  void WriteDE00(byte bValue);

};


// initialisation
void NewExtension::DoInit() {
  pC64 = (C64*)gObjectRoot.FindChild("C64");
  pCPU = (CPU6510C64*)pC64->FindChild("CPU");
  pbIO = pC64->GetIO();
  bTrapDE00 = pCPU->AllocIOTrap(this, (bpfn)ReadDE00, (pfnb)WriteDE00);
  pCPU->SetTrap(pbIO + 0x0E00, bTrapDE00);
}


// access functions
byte NewExtension::ReadDE00() {
  return 123;
}

void NewExtension::WriteDE00(byte /*bValue*/) {
}


// dll entry
BOOL WINAPI DllMain(HINSTANCE, DWORD dwReason, LPVOID) {
  static NewExtension* p;
  try {
    switch (dwReason) {
    case DLL_PROCESS_ATTACH:
      assert(p == NULL);
      p = new NewExtension;
      p->Init();
      break;
    case DLL_PROCESS_DETACH:
      assert(p != NULL);
      delete p;
      p = NULL;
      break;
    }
    return TRUE;
  } catch (...) {
    report();
    return FALSE;
  }
}
