#ifndef __SCEKERNEL_H__
#define __SCEKERNEL_H__

typedef int  (* SceKernelThreadEntry) (SceSize args, void *argp);
typedef int (*SceKernelCallbackFunction)(int arg1, int arg2, void *arg);
typedef SceUInt (*SceKernelAlarmHandler)(void *common);

typedef struct SceKernelLMOption
{
	SceSize size;
	SceUID mpidtext;
	SceUID mpiddata;
	unsigned int flags;
	char position;
	char access;
	char creserved [2];
} SceKernelLMOption;

typedef struct SceKernelThreadOptParam
{
	SceSize size;
	SceUID stackMpid;
} SceKernelThreadOptParam;

typedef struct SceKernelSemaOptParam
{
	SceSize size;
} SceKernelSemaOptParam;

typedef struct SceKernelEventFlagOptParam
{
	SceSize size;
} SceKernelEventFlagOptParam;

typedef struct SceKernelSysClock
{
	SceUInt32 low;
	SceUInt32 hi;
} SceKernelSysClock;

typedef struct SceKernelSMOption
{
	SceSize size;
	SceUID mpidstack;
	SceSize stacksize;
	int priority;
	unsigned int attribute;
} SceKernelSMOption;

typedef struct SceKernelMbxOptParam
{
	SceSize size;
} SceKernelMbxOptParam;

typedef struct SceKernelSemaInfo {
	SceSize         size;
	char            name[32];
	SceUInt         attr;
	int             initCount;
	int             currentCount;
	int             maxCount;
	int             numWaitThreads;
} SceKernelSemaInfo;

typedef struct SceKernelVplInfo {
	SceSize         size;
	char    name[32];
	SceUInt         attr;
	int     poolSize;
	int     freeSize;
	int     numWaitThreads;
} SceKernelVplInfo;

SceUID (* sceKernelAllocPartitionMemory) (SceUID partitionid, const char *name, int type, SceSize size, void *addr) = (void *) (BASE_OFFSET + 0xe6cb0);
int (* sceKernelCancelAlarm) (SceUID alarmid) = (void *) 0x09ec719c;
int (* sceKernelChangeThreadPriority) (SceUID thid, int priority) = (void *) (BASE_OFFSET + 0xe6c10);
int (* sceKernelCheckCallback) (void) = (void *) (BASE_OFFSET + 0xe6bd8);
int (* sceKernelCheckThreadStack) (void) = (void *) 0x08800b08;
int (* sceKernelClearEventFlag) (SceUID evid, u32 bits) = (void *) (BASE_OFFSET + 0xe6c90);
void (* sceKernelCpuResumeIntr) (unsigned int flags) = (void *) 0x08800af4;
void (* sceKernelCpuResumeIntrWithSync) (unsigned int flags) = (void *) 0x08800aec;
unsigned int (* sceKernelCpuSuspendIntr) (void) = (void *) 0x08800ad0;
int (* sceKernelCreateCallback) (const char *name, SceKernelCallbackFunction func, void *arg) = (void *) (BASE_OFFSET + 0xe6ca0);
SceUID (* sceKernelCreateEventFlag) (const char *name, int attr, int bits, SceKernelEventFlagOptParam *opt) = (void *) (BASE_OFFSET + 0xe6c78);
SceUID (* sceKernelCreateMbx) (const char *name, SceUInt attr, SceKernelMbxOptParam *option) = (void *) 0x09edbf1c;
SceUID (* sceKernelCreateSema) (const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option) = (void *) (BASE_OFFSET + 0xe6c50);
SceUID (* sceKernelCreateThread) (const char *name, SceKernelThreadEntry entry, int initPriority, int stackSize, SceUInt attr, SceKernelThreadOptParam *option) = (void *) (BASE_OFFSET + 0xe6be0);
SceUID (* sceKernelCreateVpl) (const char *name, int part, int attr, unsigned int size, struct SceKernelVplOptParam *opt) = (void *) 0x09edbf3c;
void (* sceKernelDcacheWritebackAll) (void) = (void *) (BASE_OFFSET + 0xe6bc8);
void (* sceKernelDcacheWritebackInvalidateAll) (void) = (void *) (BASE_OFFSET + 0xe6bd0);
void (* sceKernelDcacheWritebackInvalidateRange) (const void *p, unsigned int size) = (void *) 0x09ebd5c0;
int (* sceKernelDelayThread) (SceUInt delay) = (void *) (BASE_OFFSET + 0xe6c40);
int (* sceKernelDelayThreadCB) (SceUInt delay) = (void *) (BASE_OFFSET + 0xe6c48);
int (* sceKernelDeleteCallback) (SceUID cb) = (void *) (BASE_OFFSET + 0xe6ca8);
int (* sceKernelDeleteEventFlag) (int evid) = (void *) (BASE_OFFSET + 0xe6c80);
int (* sceKernelDeleteMbx) (SceUID mbxid) = (void *) 0x09edbf24;
int (* sceKernelDeleteSema) (SceUID semaid) = (void *) (BASE_OFFSET + 0xe6c58);
int (* sceKernelDeleteThread) (SceUID thid) = (void *) (BASE_OFFSET + 0xe6be8);
int (* sceKernelDeleteVpl) (SceUID uid) = (void *) 0x09edbf44;
int (* sceKernelEnableSubIntr) (int intno, int no) = (void *) (BASE_OFFSET + 0xe6b08);
int (* sceKernelExitDeleteThread) (int status) = (void *) (BASE_OFFSET + 0xe6c00);
void (* sceKernelExitGame) (void) = (void *) (BASE_OFFSET + 0xe6d08);
int (* sceKernelExitThread) (int status) = (void *) (BASE_OFFSET + 0xe6bf8);
int (* sceKernelFreePartitionMemory) (SceUID blockid) = (void *) (BASE_OFFSET + 0xe6cb8);
int (* sceKernelFreeVpl) (SceUID uid, void *data) = (void *) 0x09edbf54;
void * (* sceKernelGetBlockHeadAddr) (SceUID blockid) = (void *) (BASE_OFFSET + 0xe6cc0);
int (* sceKernelGetSystemTime) (SceKernelSysClock *time) = (void *) 0x09ec717c;
unsigned int (* sceKernelGetSystemTimeLow) (void) = (void *) 0x09ec718c;
SceInt64 (* sceKernelGetSystemTimeWide) (void) = (void *) 0x09ec7184;
int (* sceKernelGetThreadId) (void) = (void *) (BASE_OFFSET + 0xe6c18);
int (* sceKernelIsCpuIntrEnable) (void) = (void *) 0x08800afc;
int (* sceKernelIsCpuIntrSuspended) (unsigned int flags) = (void *) 0x08800af0;
clock_t (* sceKernelLibcClock) (void) = (void *) (BASE_OFFSET + 0xe6bb0);
int (* sceKernelLibcGettimeofday) (struct timeval *tp, struct timezone *tzp) = (void *) (BASE_OFFSET + 0xe6bc0);
time_t (* sceKernelLibcTime) (time_t *t) = (void *) (BASE_OFFSET + 0xe6bb8);
SceUID (* sceKernelLoadModule) (const char *path, int flags, SceKernelLMOption *option) = (void *) (BASE_OFFSET + 0xe6ce0);
// (* sceKernelLockLwMutex) (__) = (void *) 0x08800b00;
// (* sceKernelLockLwMutexCB) (__) = (void *) 0x08800adc;
int (* sceKernelPollEventFlag) (int evid, u32 bits, u32 wait, u32 *outBits) = (void *) 0x09ed7128;
int (* sceKernelPollSema) (SceUID semaid, int signal) = (void *) (BASE_OFFSET + 0xe6c70);
void (* sceKernelPowerTick) (void) = (void *) (BASE_OFFSET + 0xe6ba8);
int (* sceKernelReceiveMbx) (SceUID mbxid, void **pmessage, SceUInt *timeout) = (void *) 0x09edbf34;
// (* sceKernelReferLwMutexStatus) (__) = (void *) 0x08800b04;
// (* sceKernelReferLwMutexStatusByID) (__) = (void *) 0x08800938;
int (* sceKernelReferSemaStatus) (SceUID semaid, SceKernelSemaInfo *info) = (void *) 0x09ebd5b8;
int (* sceKernelReferVplStatus) (SceUID uid, SceKernelVplInfo *info) = (void *) 0x09edbf5c;
int (* sceKernelRegisterExitCallback) (int cbid) = (void *) (BASE_OFFSET + 0xe6d10);
int (* sceKernelRegisterSubIntrHandler) (int intno, int no, void *handler, void *arg) = (void *) (BASE_OFFSET + 0xe6af8);
// (* sceKernelRegisterUserSpaceIntrStack) (__) = (void *) 0x08800920;
int (* sceKernelReleaseSubIntrHandler) (int intno, int no) = (void *) (BASE_OFFSET + 0xe6b00);
int (* sceKernelSelfStopUnloadModule) (int unknown, SceSize argsize, void *argp) = (void *) (BASE_OFFSET + 0xe6d00);
int (* sceKernelSendMbx) (SceUID mbxid, void *message) = (void *) 0x09edbf2c;
SceUID (* sceKernelSetAlarm) (SceUInt clock, SceKernelAlarmHandler handler, void *common) = (void *) 0x09ec7194;
int (* sceKernelSetEventFlag) (SceUID evid, u32 bits) = (void *) (BASE_OFFSET + 0xe6c88);
int (* sceKernelSignalSema) (SceUID semaid, int signal) = (void *) (BASE_OFFSET + 0xe6c60);
int (* sceKernelSleepThread) (void) = (void *) (BASE_OFFSET + 0xe6c20);
int (* sceKernelStartModule) (SceUID modid, SceSize argsize, void *argp, int *status, SceKernelSMOption *option) = (void *) (BASE_OFFSET + 0xe6ce8);
int (* sceKernelStartThread) (SceUID thid, SceSize arglen, void *argp) = (void *) (BASE_OFFSET + 0xe6bf0);
SceUID (* sceKernelStderr) (void) = (void *) (BASE_OFFSET + 0xe6cd8);
SceUID (* sceKernelStdin) (void) = (void *) (BASE_OFFSET + 0xe6cc8);
SceUID (* sceKernelStdout) (void) = (void *) (BASE_OFFSET + 0xe6cd0);
int (* sceKernelStopModule) (SceUID modid, SceSize argsize, void *argp, int *status, SceKernelSMOption *option) = (void *) (BASE_OFFSET + 0xe6cf0);
int (* sceKernelSuspendThread) (SceUID thid) = (void *) (BASE_OFFSET + 0xe6c30);
int (* sceKernelSysClock2USec) (SceKernelSysClock *clock, unsigned int *low, unsigned int *high) = (void *) 0x09ec7174;
int (* sceKernelTerminateDeleteThread) (SceUID thid) = (void *) (BASE_OFFSET + 0xe6c08);
int (* sceKernelTerminateThread) (SceUID thid) = (void *) 0x09ec711c;
int (* sceKernelTryAllocateVpl) (SceUID uid, unsigned int size, void **data) = (void *) 0x09edbf4c;
// (* sceKernelTryLockLwMutex) (__) = (void *) 0x08800b0c;
int (* sceKernelUnloadModule) (SceUID modid) = (void *) (BASE_OFFSET + 0xe6cf8);
// (* sceKernelUnlockLwMutex) (__) = (void *) 0x08800ad4;
int (* sceKernelWaitEventFlag) (int evid, u32 bits, u32 wait, u32 *outBits, SceUInt *timeout) = (void *) (BASE_OFFSET + 0xe6c98);
int (* sceKernelWaitSema) (SceUID semaid, int signal, SceUInt *timeout) = (void *) (BASE_OFFSET + 0xe6c68);
int (* sceKernelWaitThreadEnd) (SceUID thid, SceUInt *timeout) = (void *) (BASE_OFFSET + 0xe6c38);
int (* sceKernelWakeupThread) (SceUID thid) = (void *) (BASE_OFFSET + 0xe6c28);

int LoadStartModule(char *path)
{
    u32 loadResult;
    u32 startResult;
    int status;

    loadResult = sceKernelLoadModule(path, 0, NULL);
    if (loadResult & 0x80000000){
       return -1;
    }else{
       startResult = sceKernelStartModule(loadResult, 0, NULL, &status, NULL);
    }

    if (loadResult != startResult){
       return -2;
    }
    return 0;
}

int StopUnloadModule(SceUID modID){
    int status;
    sceKernelStopModule(modID, 0, NULL, &status, NULL);
    sceKernelUnloadModule(modID);
    return 0;
}

#endif
