#include <windows.h>
#include <wchar.h>

#ifdef _DEBUG
#define LEAK_CHECK //メモリリーク検出（しない場合はコメントアウト）
#endif
#ifdef LEAK_CHECK
#include <crtdbg.h>
#endif

#include "kbpsf_module.h"
#include "kbpsf_decoder.h"
#include "kbpsf_config.h"
#include "viopsf/pversion.h"

#ifdef _DEBUG
static const DWORD kbpsf_Version = 0x7FFFFFFF; //デバッグ時は優先度最大
#define KBPSF_VERSION_STR L"0x7FFFFFFF(Debug)"
#else
static const DWORD kbpsf_Version = 108;
#define KBPSF_VERSION_STR L"1.08"
#endif

// {26A3FBCC-79E7-4477-B5AC-F191FE6C3C0B}
static const GUID kbpsf_GUID =
{ 0x26a3fbcc, 0x79e7, 0x4477, { 0xb5, 0xac, 0xf1, 0x91, 0xfe, 0x6c, 0x3c, 0xb } };

static const wchar_t kbpsf_Description[] = L"PlayStation Sound Format(PSF) Decoder v" KBPSF_VERSION_STR " based on viopsf v" XSFDRIVER_VERSIONS " / PCSXR "  CORE_VERSIONS ;
static const wchar_t kbpsf_Copyright[] = L"kbpsf.kpi Copyright (C) 2016-2019 Kobarin\n"
                                          "viopsf Copyright (C) 2015-2019 Unknown Japanese author\n"
                                          "\n"
                                          CORE_COPYRIGHT 
                                          "\n"
                                          ADDITIONAL_LIBRARY_COPYRIGHT
                                          "\n"
                                          "PeopsSound Copyright (C) 2002-2015 Pete Bernert\n"
                                          "\n"
                                          "mednafen Copyright (C) 2005-2015 Mednafen Team\n"
                                          "\n"
                                          "MAME\n"
                                          "    copyright-holders: pSXAuthor, R. Belmont\n"
                                          "    Sony PlayStation SPU (CXD2922BQ/CXD2925Q) emulator\n"
                                          "        by pSXAuthor\n"
                                          "        MAME adaptation by R. Belmont\n"
                                          "\n"
                                          "zlib (C) 1995-2017 Jean-loup Gailly and Mark Adler";
//////////////////////////////////////////////////////////////////////////////
static const DWORD kbpsf_MultipleInstance = KPI_MULTINST_ONE;
static const wchar_t kbpsf_SupportExts[] = L".psf/.minipsf";
static const wchar_t kbpsf_MultiSongExts[] = L"";
static const DWORD kbpsf_SupportTagInfo = //KPI_DECODER_MODULEINFO::TAG_TITLE |
                                          //KPI_DECODER_MODULEINFO::TAG_EXTRA |
                                           0;
static const DWORD kbpsf_SupportConfig = 1;
static void* kbpsf_Reserved1 = NULL;
static void* kbpsf_Reserved2 = NULL;
HINSTANCE g_hKpi = NULL;
//////////////////////////////////////////////////////////////////////////////
KbPsfDecoderModule::KbPsfDecoderModule(IKpiConfig *pConfig)
    :m_ModuleInfo{
        sizeof(KPI_DECODER_MODULEINFO), //cb(=sizeof(KPI_DECODER_MODULEINFO))
        KPI_DECODER_MODULE_VERSION,     //dwModuleVersion(=KPI_DECODER_MODULE_VERSION)
        kbpsf_Version,                 //dwPluginVersion
        kbpsf_MultipleInstance,
        kbpsf_GUID,
        kbpsf_Description,
        kbpsf_Copyright,
        kbpsf_SupportExts,
        kbpsf_MultiSongExts,
        kbpsf_Reserved1,
        kbpsf_Reserved2,
        kbpsf_SupportTagInfo,
        kbpsf_SupportConfig,
        0, 0, 0, 0                      //reserved
     }
{
    m_pConfig = pConfig;
    KbPsfDecoder::Init(pConfig);
    pConfig->AddRef();
}
//////////////////////////////////////////////////////////////////////////////
KbPsfDecoderModule::~KbPsfDecoderModule(void)
{
    KbPsfDecoder::Deinit();
    m_pConfig->Release();
}
//////////////////////////////////////////////////////////////////////////////
void  WINAPI KbPsfDecoderModule::GetModuleInfo(const KPI_DECODER_MODULEINFO **ppInfo)
{
    *ppInfo = &m_ModuleInfo;
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbPsfDecoderModule::Open(const KPI_MEDIAINFO *cpRequest,
                                         IKpiFile     *pFile,   //音楽データ
                                         IKpiFolder   *pFolder, //音楽データがあるフォルダ
                                         IKpiDecoder **ppDecoder)
{
    KbPsfDecoder *pDecoder = new KbPsfDecoder(m_pConfig);
    DWORD dwCount = pDecoder->Open(cpRequest, pFile, pFolder);
    if(dwCount == 0){
        *ppDecoder = NULL;
        delete pDecoder;
        return 0;
    }
    *ppDecoder = pDecoder;
    return dwCount;
}
//////////////////////////////////////////////////////////////////////////////
BOOL  WINAPI KbPsfDecoderModule::EnumConfig(IKpiConfigEnumerator *pEnumerator)
{
    return kbpsf_EnumConfig(pEnumerator);
}
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI KbPsfDecoderModule::ApplyConfig(const wchar_t *cszSection,
                                             const wchar_t *cszKey,
                                             INT64 nValue,
                                             double dValue,
                                             const wchar_t *cszValue)
{
    return kbpsf_ApplyConfig(m_pConfig, cszSection, cszKey, nValue, dValue, cszValue);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT WINAPI kpi_CreateInstance(REFIID riid, void **ppvObject, IKpiUnknown *pUnknown)
{
    *ppvObject = NULL;
    if(!IsEqualIID(riid, IID_IKpiDecoderModule)){
        return E_NOINTERFACE;
    }
    IKpiConfig *pConfig = NULL;
    kpi_CreateConfig(pUnknown, &kbpsf_GUID, NULL, &pConfig);
    IKpiDecoderModule *pDecoderModule = new KbPsfDecoderModule(pConfig);
    *ppvObject = pDecoderModule;
    pConfig->Release();//KbPsfDecoderModule 内で AddRef しているので必ず必要
    return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
//DllMain
/////////////////////////////////////////////////////////////////////////////
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    {
#ifdef LEAK_CHECK
        //メモリリーク検出
        int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
        //tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
        tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
        //tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
        _CrtSetDbgFlag(tmpDbgFlag);
#endif
        g_hKpi = hModule;
        DisableThreadLibraryCalls(hModule);
        break;
    }
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
