#if 0

#include <windows.h>
#include <stdio.h>
#include <crtdbg.h>
#include "kmp_pi.h"


#ifdef _DEBUG
#define KMPMODULE_PLUGIN_VERSION 0x7FFFFFFF
#else
#define KMPMODULE_PLUGIN_VERSION 1
#endif

/* 512 Kb 68K memory buffer */
#define MEMORY (1<<19)

extern "C"{

#include "sc68app/SC68.h"
#include "sc68app/SC68app.h"
#include "file68/SC68error.h"
#include "file68/SC68utils.h"
#include "file68/SC68file.h"
#ifdef WANT_BROWSEINFO_68
# include "browse68/SC68browse.h"
#endif
#include "file68/SC68os_general.h"
#include "sc68app/SC68os_interface.h"
#include "sc68app/SC68play.h"
#include "sc68app/SC68delay.h"
#include "sc68app/SC68mixer.h"

#include "io68/io68.h" //

};

static HINSTANCE g_hKpi = NULL;
static SC68app_t app;

/* Initialize 68K stuff * : alloc memory
 */
static int init_68K(reg68_t * r, u32 sz)
{
  if (EMU68_init(sz) < 0)
    return SC68error_add(EMU68error_get());
  *r = reg68;
  r->sr = 0x2000;
  r->a[7] = sz - 4;
  if (YM_init() < 0)
    return SC68error_add("Yamaha 2149 emulator init failed");
  if (MW_init() < 0)
    return SC68error_add("Microwire emulator init failed");
  if (MFP_init() < 0)
    return SC68error_add("MFP emulator init failed");
  if (PL_init() < 0)
    return SC68error_add("Paula emulator init failed");
  return 0;
}

/* Set sc68app struct to default value
 */
static void set_sc68app_default(SC68app_t * app)
{
  memset(app, 0, sizeof(*app));
  app->cur_track = -1;
  SC68config_default(&app->config);
}

static unsigned int TimeToTrack(disk68_t *d, int n)
{
  int i;
  unsigned int cnt = 0;
  if (n >= d->nb_six) {
    n = d->nb_six - 1;
  }
  for (i=0; i<n; ++i) {
    cnt += d->mus[i].time * 1000;
  }
  return cnt;
}

volatile struct change_track_s {
  int track;
  int time;
} change_track = { -1, -1 };

static void ClearChangeTrack(void)
{
  change_track.track = -1;
  change_track.time = -1;
}

static void SetChangeTrack(int trk, int tim)
{
  change_track.time = tim;
  change_track.track = trk;
}

static void ApplyChangeTrack(void)
{
  if (change_track.track >= 0) {
    SC68track(&app, change_track.track);
    ClearChangeTrack();
  }
}

/* any one-time initialization goes here (configuration reading, etc) */
void init()
{
  int r, frq, hres;
  char execname[512];

  //SC68os_pdebug("\nINIT XMMS68 pluggin\n");

  hres = GetModuleFileName((HMODULE) g_hKpi, execname, sizeof(execname));
  if(hres<0) {
    execname[0] = 0;
  }

  /* check whether EMU68 is compiled without debug option */
  if (EMU68_sizeof_reg68() != sizeof(reg68_t)) {
    //SC68error_add
    //    ("Internal : Bad EMU68 version : should not define SC68DEBUG ...");
    return;
  }

  /* Set default configuration */
  set_sc68app_default(&app);

  /* Get exec path : for resource */
  if (SC68os_get_exec_path(execname) < 0) {
    return;
  }

  /* Get the config file OR create if it doesn't exist */
  //SC68os_pdebug("Read config file ...\n");
  if (SC68config_load(&app.config,
                      SC68os_resource_name(SC68rsc_config,
                                           SC68_DEFAULT_CONFIG_FILE)) < 0) {
    SC68error_get();
    SC68error_get();
    SC68config_save(&app.config,
                    SC68os_resource_name(SC68rsc_config,
                                         SC68_DEFAULT_CONFIG_FILE));
  }
  //SC68os_pdebug("OK\n");

  SC68config_display(&app.config);

  /* Open application ( OS dependant code ) */
  r = SC68os_interface_open(execname, &app);

  /* Open error */
  if (r < 0) {
    return;
  }

  /* Copy config parameters to app */
  SC68app_configure(&app);

  /* Delay init : from config file parameters ( SC68app_configure() ) */
  app.delay.buffer_size = SC68delay_init(app.delay.buffer_size);
  if (app.delay.buffer_size < 0)
    return;

  frq = (int) app.mix.real_frq;

  /* First instance : Do mucho initialization */
  if (r > 0) {
    /* 68K & IO-Emulators init */
    if (init_68K(&app.reg68, MEMORY)) {
      return;
    }
    //SC68os_pdebug("68K emulator init : OK\n");
    /* IO replay frequency init */
    app.mix.real_frq = 44100;
    YM_set_replay_frq(app.mix.real_frq);
    MW_set_replay_frq((int) app.mix.real_frq);
    PL_set_replay_frq((int) app.mix.real_frq);
    app.mix.buf = YM_get_buffer();
  }
}

/* one-time deinit, such as memory freeing */
void quit()
{
  EMU68_kill();
  SC68delay_kill();
  SC68os_interface_close(&app);
}

// render 576 samples into buf.
// note that if you adjust the size of sample_buffer, for say, 1024
// sample blocks, it will still work, but some of the visualization
// might not look as good as it could. Stick with 576 sample blocks
// if you can, and have an additional auxiliary (overflow) buffer if
// necessary..
static int get_samples(char *buf, int max)
{
	int sended = 0;
  const unsigned int sign = SC68MIXER_CHANGE_SIGN;
  unsigned int cycle_this_pass = app.mix.cycleperpass;

  if(!app.ready || !app.cur_mus) {
    return 0;
  }

  while (max>0) {
    int tosend;

    if( ! app.mix.buflen ) {
#ifdef _WRAPPER_
      EMU68_cycle(cycle_this_pass);
#else
      EMU68_level_and_interrupt(cycle_this_pass);
#endif


      /* YM ??? */
      if (app.cur_mus->flags.ym)
        app.mix.buflen = YM_mix(cycle_this_pass);
      else
        app.mix.buflen = app.mix.stdbuflen;

      app.mix.buf = YM_get_buffer();

      /* MW ??? */
      if (app.cur_mus->flags.ste) {
        MW_mix(app.mix.buf, app.reg68.mem, app.mix.buflen);
        if (sign) {
          SC68mixer_stereo_16_LR(app.mix.buf,app.mix.buf, app.mix.buflen, sign);
        }
      }
      /* Paula ??? */
      else if (app.cur_mus->flags.amiga) {
        PL_mix(app.mix.buf, app.reg68.mem, app.reg68.mem + app.reg68.memsz,
               app.mix.buflen);

        SC68mixer_stereo_16_LR(app.mix.buf,app.mix.buf, app.mix.buflen,
                               SC68MIXER_CHANGE_SIGN);

        SC68mixer_blend_LR(app.mix.buf, app.mix.buf, app.mix.buflen,
                           app.mix.amiga_blend , sign);
      }
      /* Do stereo my self */
      else {
        SC68mixer_dup_L_to_R(app.mix.buf, app.mix.buf, app.mix.buflen, sign);
      }

      if (app.delay.onoff) {
        /* Apply delay ... */
        int delay;
        const int shift = 0;

        if (app.delay.time < 0)
          delay = (app.mix.buflen << shift) / -app.delay.time;
        else
          delay = (app.mix.buflen * app.delay.time) >> shift;
        if (!app.delay.lr)
          /* Delay ring */
          SC68delay(app.mix.buf, app.mix.buflen, delay, app.delay.strength, sign);
        else
          /* L/R spacializer delay */
          SC68delay_LR(app.mix.buf, app.mix.buflen, delay);
      }


      /* Advance time */
      SC68app_advance_time(&app);

      /* Reach end of track */
      if (app.time.elapsed > app.time.track) {
        if(app.cur_track+1 >= app.cur_disk->nb_six) {
          memset(buf,0,max*4);
          return -1;
        } else {
          SC68track(&app, app.cur_track+1);
        }
      }
    }

    tosend = (app.mix.buflen > max) ? max : app.mix.buflen;
    memcpy(buf, app.mix.buf, tosend * 4);
    buf += tosend * 4;
    max -= tosend;
    app.mix.buf += tosend;
    app.mix.buflen -= tosend;
    sended += tosend;
  }
  return sended;
}

class KbSC68Decoder
{
    char m_szFileName[MAX_PATH*2];
    BOOL m_bStart;
public:
    BOOL  __fastcall Open(const char *cszFileName, SOUNDINFO *pInfo);
    DWORD __fastcall Render(BYTE *Buffer, DWORD dwSize);
    DWORD __fastcall SetPosition(DWORD dwPos);
    void __fastcall Close(void);
    KbSC68Decoder(void);
    ~KbSC68Decoder(void);
};
static KbSC68Decoder *g_pActive = NULL;

KbSC68Decoder::KbSC68Decoder(void)
{
    m_bStart = FALSE;
    m_szFileName[0] = 0;
    if(!g_pActive){
        g_pActive = this;
    }
}
KbSC68Decoder::~KbSC68Decoder(void)
{
    Close();
    if(g_pActive == this){
        g_pActive = NULL;
    }
}
void KbSC68Decoder::Close(void)
{
    if(m_szFileName[0]){
        m_bStart = FALSE;
        m_szFileName[0] = 0;
        SC68app_eject(&app);
        ClearChangeTrack();
    }
}
BOOL __fastcall KbSC68Decoder::Open(const char *cszFileName, SOUNDINFO *pInfo)
{
    if(!pInfo)return FALSE;
    ZeroMemory(pInfo, sizeof(SOUNDINFO));
    if(g_pActive != this){
        return FALSE;
    }
    disk68_t *d;
    /* Stop sc68 processing */
    SC68app_desactiv(&app);
	app.pause=0;
    /* Load disk and generate browse info */
    char filename[MAX_PATH*2];
    lstrcpyn(filename, cszFileName, sizeof(filename));
    d = SC68app_load_diskfile(SC68os_absolute_fname(filename), 0);
    if (!d) {
        goto error;
    }
    /* Set as current application disk, load default track.
     * If app.force_track == 0, disk default track is loaded, else app.force_track-1 is loaded
    */
    if(SC68load(&app, d) < 0) {
        goto error;
    }
    ClearChangeTrack();
    /* Start current track */
    if (SC68play(&app) < 0) {
        goto error;
    }
    SC68app_activ(&app);
    pInfo->dwSamplesPerSec = 44100;
    pInfo->dwChannels = 2;
    pInfo->dwBitsPerSample = 16;
    pInfo->dwLength = app.cur_disk ? app.cur_disk->time * 1000 : 0;
    pInfo->dwSeekable = 0;
    pInfo->dwUnitRender = 576*2*2;
    pInfo->dwReserved1 = 0;
    pInfo->dwReserved2 = 0;
    strcpy(m_szFileName, cszFileName);
    return TRUE;
error:
    if(d){
        SC68_free(d);
    }
    SC68app_desactiv(&app);
    return FALSE;
}
DWORD __fastcall KbSC68Decoder::Render(BYTE *Buffer, DWORD dwSize)
{
    m_bStart = TRUE;
    ApplyChangeTrack();
    int read = 0;
    __try{
        read = get_samples((char*)Buffer, dwSize/4);
    }
    __except(EXCEPTION_EXECUTE_HANDLER){
        read = 0;
    }
    if(read > 0){
        return read*4;
    }
    return 0;
}
DWORD __fastcall KbSC68Decoder::SetPosition(DWORD dwPos)
{
    if(dwPos == 0 && !m_bStart)return 0;
    if(m_szFileName[0]){
        char szFileName[sizeof(m_szFileName)];
        strcpy(szFileName, m_szFileName);
        Close();
        SOUNDINFO info;
        Open(szFileName, &info);
    }
    return 0;
}

static int g_nInitCount = 0;
static void WINAPI kmp_Init (void)
{
    if(g_nInitCount == 0){
        g_nInitCount++;
        init();
    }
}
static void WINAPI kmp_Deinit (void)
{
    if(g_nInitCount > 0){
        g_nInitCount--;
        quit();
    }
}
static HKMP WINAPI kmp_Open (const char *cszFileName, SOUNDINFO *pInfo)
{
    KbSC68Decoder *sc68 = new KbSC68Decoder;
    if(sc68->Open(cszFileName, pInfo)){
        return (HKMP)sc68;
    }
    else{
        delete sc68;
        return NULL;
    }
}

static void WINAPI kmp_Close (HKMP hKMP)
{
    KbSC68Decoder *sc68 = (KbSC68Decoder*)hKMP;
    if(sc68){
        delete sc68;
    }
}

static DWORD WINAPI kmp_Render (HKMP hKMP, BYTE* Buffer, DWORD dwSize)
{
    KbSC68Decoder *sc68 = (KbSC68Decoder*)hKMP;
    if(sc68){
        return sc68->Render(Buffer, dwSize);
    }
    return 0;
}

static DWORD WINAPI kmp_SetPosition (HKMP hKMP, DWORD dwPos)
{
    KbSC68Decoder *sc68 = (KbSC68Decoder*)hKMP;
    if(sc68)
        return sc68->SetPosition(dwPos);
    return 0;
}

BOOL APIENTRY DllMain (HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call){
        case DLL_PROCESS_ATTACH:{
            g_hKpi = (HINSTANCE)hModule;
            DisableThreadLibraryCalls((HMODULE)hModule);
            break;
        }
        case DLL_PROCESS_DETACH:{
            break;
        }
    }
    return TRUE;
}

KMPMODULE* WINAPI kmp_GetTestModule (void)
{
    static const char *ppszSupportExts[] = {".sc68", NULL};
    static KMPMODULE MOD = 
    {
        KMPMODULE_VERSION,
        KMPMODULE_PLUGIN_VERSION,
        "Copyright (C) 1998-2003 sashipa, Ben(jamin) Gerard, and Kobarin",
        "sashipa Atari-ST & Amiga music player for KbMedia Player (based on in_sc68.dll v1.2)",
        ppszSupportExts,
        0,
        kmp_Init,
        kmp_Deinit,
        kmp_Open,
        NULL,
        kmp_Close,
        kmp_Render,
        kmp_SetPosition
    };
#ifdef _DEBUG
    //メモリリーク検出
    static int DbgFlagInit = 0;
    if(!DbgFlagInit){
        DbgFlagInit = 1;
        int DbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
        //DbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
        DbgFlag |= _CRTDBG_LEAK_CHECK_DF;
        //DbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
        _CrtSetDbgFlag(DbgFlag);
    }
#endif
    return &MOD;
}

#endif
