/* 	
Xenon plugins
*/
#include <xtl.h>
#include <gccore.h>
#include <stdint.h>
#include <sys/types.h>

#include "GPUXenonStruct.h"
#include "GPUXenon.h"


#define CORE_ID 4
#define THREADCOUNT 1

static HANDLE h_sepGpuThread=NULL;

static void InitSemaphore()
{
	h_sepGpuThread = CreateSemaphoreA( 
		NULL,              // default security attributes
		THREADCOUNT,             // initially not owned
		THREADCOUNT,
		"GPU Plugins Thread"
	);
}


extern "C" long GPU__open(void) {
	return GPUXenon::GPUXenonOpen();
	return 0; 
}

extern "C" long GPU__init(void) { 
	//create texture
	return GPUXenon::GPUXenonInit();
}

extern "C" long GPU__shutdown(void) {
	//free everything
	return GPUXenon::GPUXenonShutdown();
}

extern "C" long GPU__close(void) 
{ 
	return GPUXenon::GPUXenonClose();
}

struct ThreadDataUlAptrIB{
	unsigned long *a;
	int b;
};

struct ThreadDataUlAptrUlB{
	unsigned long *a;
	unsigned long b;
};

static DWORD  WINAPI ThreadedWriteStatus(void * a)
{
	if(a==NULL)
		return 0;
	WaitForSingleObject(h_sepGpuThread, INFINITE);
	GPUXenon::GPUXenonWriteStatus((unsigned long)&a);
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
	return 0;
};

static VOID WINAPI ThreadedWriteData(void * a)
{
	if(a==NULL)
		return;
	WaitForSingleObject(h_sepGpuThread, INFINITE);
	GPUXenon::GPUXenonWriteData((unsigned long)&a);
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
};

static VOID WINAPI ThreadedWriteDataMem(void * a)
{
	if(a==NULL)
		return;
	WaitForSingleObject(h_sepGpuThread, INFINITE);

	struct ThreadDataUlAptrIB *s=(ThreadDataUlAptrIB*)a;

	GPUXenon::GPUXenonWriteDataMem(s->a,s->b);
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
};

static unsigned long WINAPI ThreadedReadStatus(void * a)
{
	WaitForSingleObject(h_sepGpuThread, INFINITE);
	unsigned long b = GPUXenon::GPUXenonReadStatus();
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
	return b;
};

static unsigned long WINAPI ThreadedReadData(void * a)
{
	WaitForSingleObject(h_sepGpuThread, INFINITE);
	unsigned long b = GPUXenon::GPUXenonReadData();
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
	return b;
};

static void WINAPI ThreadedReadDataMem(void * a)
{
	if(a==NULL)
		return;

	struct ThreadDataUlAptrIB *s=(ThreadDataUlAptrIB*)a;

	WaitForSingleObject(h_sepGpuThread, INFINITE);
	GPUXenon::GPUXenonReadDataMem(s->a,s->b);
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
};


static long WINAPI ThreadedDmaChain(void * a)
{
	struct ThreadDataUlAptrUlB *s=(ThreadDataUlAptrUlB*)a;

	WaitForSingleObject(h_sepGpuThread, INFINITE);
	long b =GPUXenon::GPUXenonDmaChain(s->a,s->b);
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
	return b;
};

static void WINAPI ThreadedUpdateLace(void * a)
{
	WaitForSingleObject(h_sepGpuThread, INFINITE);
	GPUXenon::GPUXenonUpdateLace();
	ReleaseSemaphore(h_sepGpuThread,1,NULL);
};
#define CREATETHREAD(X,Y)\
	HANDLE hThread = CreateThread( NULL, 0, X, (void*)Y, 0, NULL );\
    if( hThread )\
    {\
        CloseHandle( hThread );\
		DebugBreak();\
    }\
//Write
extern "C" void GPU__writeStatus(unsigned long a)
{
	//CREATETHREAD(ThreadedWriteStatus,a);
	GPUXenon::GPUXenonWriteStatus(a);
}

extern "C" void GPU__writeData(unsigned long a)
{
	GPUXenon::GPUXenonWriteData(a);
}

extern "C" void GPU__writeDataMem(unsigned long *a, int b){
	GPUXenon::GPUXenonWriteDataMem(a, b); 
}
//Read
extern "C" unsigned long GPU__readStatus(void) 
{ 
	return  GPUXenon::GPUXenonReadStatus(); 
}

extern "C" unsigned long GPU__readData(void) 
{ 
	return  GPUXenon::GPUXenonReadData();  
}

extern "C" void GPU__readDataMem(unsigned long *a, int b){
	GPUXenon::GPUXenonReadDataMem(a, b); 
};

extern "C" long GPU__dmaChain(unsigned long *a ,unsigned long b) 
{
	return  GPUXenon::GPUXenonDmaChain(a,b); 
}

extern "C" void GPU__updateLace(void) 
{
	GPUXenon::GPUXenonUpdateLace(); 
}

extern "C" long GPU__freeze(uint32_t a, GPUFreeze_t *b){
	return GPUXenon::GPUXenonFreeze(a,b);
};
/*
extern "C" long GPU__getScreenPic(unsigned char *){
	return 1;
};

extern "C" long GPU__showScreenPic(unsigned char *){
	return 1;
};

extern "C" void GPU__clearDynarec(void (CALLBACK *callback)(void)){
	psxCpu->Reset();
};
*/