// nvdxtlib.cpp : Defines the entry point for the console application.
//

#include "dxtlib.h"

// library name
static const char* Name_Library = "nvdxtlib.dll";

// prototypes for the wrapper functions
typedef NV_ERROR_CODE (*WRAPPER_CompressDXT)(const unsigned char*, size_t, size_t, size_t, nvPixelOrder, nvCompressionOptions*, DXTWriteCallback, const RECT*);
typedef const char* (*WRAPPER_CompressDXT_GetErrorString)(NV_ERROR_CODE);
typedef const char* (*WRAPPER_CompressDXT_GetVersionString)();

// names for the wrapper function imports
static const char* Name_CompressDXT = "?Asura_PC_CompressDXT@@YA?AW4NV_ERROR_CODE@@PBEIIIW4nvPixelOrder@@PAVnvCompressionOptions@@P6A?AW41@PBXIPBUMIPMapData@@PAX@ZPBUtagRECT@@@Z";
static const char* Name_CompressDXT_GetErrorString = "?Asura_PC_CompressDXT_GetErrorString@@YAPBDW4NV_ERROR_CODE@@@Z";
static const char* Name_CompressDXT_GetVersionString = "?Asura_PC_CompressDXT_GetVersionString@@YAPBDXZ";

// DLL handle
HMODULE hWrapperDLL = NULL;

// String used by the error/version functions when the wrapper system breaks
const char* wrapperError = "NVDXT Wrapper error!";

static void UnloadWrapper()
{
	if(!hWrapperDLL) return;
	FreeLibrary(hWrapperDLL);
	hWrapperDLL = NULL;
}

static bool LoadWrapper()
{
	if(hWrapperDLL) UnloadWrapper();
	hWrapperDLL = LoadLibrary(Name_Library);
	if(!hWrapperDLL) return false;
	return true;
}

NV_ERROR_CODE Asura_PC_CompressDXT(
		const unsigned char * srcImage,
        size_t width,
        size_t height,
        size_t byte_pitch,
        nvPixelOrder pixelOrder,

        nvCompressionOptions * options,
        DXTWriteCallback fileWriteRoutine,  // call to .dds write routine
        const RECT * rect)
{
	// Assume failure
	NV_ERROR_CODE result = NV_FAIL;

	// Load the wrapper DLL
	if(!LoadWrapper()) return result;

	// Get the wrapper function we want from it
	WRAPPER_CompressDXT pfnCompressDXT = (WRAPPER_CompressDXT)GetProcAddress(hWrapperDLL, Name_CompressDXT);

	// Call it
	if(pfnCompressDXT)
	{
		result = (pfnCompressDXT)(
			srcImage,
		    width,
		    height,
		    byte_pitch,
		    pixelOrder,
		    options,
		    fileWriteRoutine,
		    rect);
	}

	// Unload the wrapper
	UnloadWrapper();

	return result;
}

const char* Asura_PC_CompressDXT_GetErrorString(NV_ERROR_CODE eError)
{
	// Assume failure
	const char* result = wrapperError;

	// Load the wrapper
	if(!LoadWrapper()) return result;

	// Get the wrapper function that we want
	WRAPPER_CompressDXT_GetErrorString pfnGetErrorString = (WRAPPER_CompressDXT_GetErrorString)GetProcAddress(hWrapperDLL, Name_CompressDXT_GetErrorString);

	// Call it
	if(pfnGetErrorString)
	{
		result = (pfnGetErrorString)(eError);
	}

	// Unload the wrapper
	UnloadWrapper();

	return result;
}

const char* Asura_PC_CompressDXT_GetVersionString(void)
{
	// Assume failure
	const char* result = wrapperError;

	// Load the wrapper
	if(!LoadWrapper()) return result;

	// Get the wrapper function that we want
	WRAPPER_CompressDXT_GetVersionString pfnGetVersionString = (WRAPPER_CompressDXT_GetVersionString)GetProcAddress(hWrapperDLL, Name_CompressDXT_GetVersionString);

	// Call it
	if(pfnGetVersionString)
	{
		result = (pfnGetVersionString)();
	}

	// Unload the wrapper
	UnloadWrapper();

	return result;
}
