#include "stdafx.h"
#include "types.h" 
#include "kernel.h"
#include "hud.h"
#include "dvar.h"
#include "smc.h"
#include "XeCrypt.h"
#include "socket.h"
#include <iostream>
#include <string>
#include <vector>
#include <time.h>

#define config_dvars           "game:\\iKonroi\\config.cfg"
#define config_infectAll       "game:\\iKonroi\\dvar\\infectall.cfg"
#define config_challengeTable  "game:\\iKonroi\\rank\\challengeTable.cfg"
#define config_cohost          "game:\\iKonroi\\cohost.tags"
#define config_vip             "game:\\iKonroi\\vip.tags"

using namespace std;


#define BUTTON_A                  "n 25"
#define BUTTON_B                  "n 23"
#define BUTTON_X                  "n 11"
#define BUTTON_Y                  "n 28"
#define BUTTON_RS                "n 3"
#define BUTTON_LS                "n 9"
#define BUTTON_RB                "n 5"
#define BUTTON_LB                "n 7"
#define BUTTON_RT                "n 1"
#define BUTTON_LT                "n 13"
#define BUTTON_DPADUP            "n 16"
#define BUTTON_DPADDOWN          "n 18"
#define BUTTON_DPADLEFT          "n 19"
#define BUTTON_DPADRIGHT          "n 21"
#define BUTTON_BACK              "n 30"
#define BUTTON_START              "n 27"

typedef VOID (__cdecl * SV_Cmd_TokenizeString_t)(const char * text_in);
typedef VOID (__cdecl * ClientCommand_t)(DWORD clientIndex);
typedef VOID (__cdecl * SV_Cmd_EndTokenizedString_t)();
typedef int (__cdecl * irand_t)(int min, int max);

extern "C" 
{
    void __stdcall HalSendSMCMessage(void* input, void* output);
    LPVOID MmGetPhysicalAddress(LPVOID Address, int Size);
}

bool hasRan;
byte host;

dvar_s * g_gametype;
char *gametype;

#define _Thread DWORD WINAPI
#define _Hook void
bool ended;
bool fog_enabled;
bool cl_ingame;
bool verifection = {false};

byte setting;
vector< string > cohost;
vector< string > vip;


unsigned short timer_newsbar = {1875};
byte timer_clicks;
byte timer_pulse;
unsigned short timer_credit;
byte credit;
byte pulse_text_color;
bool pulse_text_reverse;

byte fog = {1};
byte timer_fog = {1};
byte max_unlock_all_at_once = {0};

byte Client = {0};


HANDLE hThreadInfectAll;
HANDLE hThreadDerank;
HANDLE hThreadMain;
HANDLE hThreadEnd;
HANDLE hFXThreadHeart;
HANDLE hFXThreadNewsbar;
DWORD hThreadInfectAllId;
DWORD dwThreadDerankId;
DWORD dwThreadMainId;
DWORD dwThreadEndId;
DWORD dwFXThreadHeartId;
DWORD dwFXThreadNewsbarId;

bool bThreadInfectAll;


char CurrentGamertag[18][15];
XenonUserData * xenonUserData = (XenonUserData *)0x838BA820;

int FindHost()
{
  int HostIndex;
  for( int clientID = 0; clientID < 18; clientID++)
    if(!strcmp(xenonUserData[0].name,CurrentGamertag[clientID]))

  HostIndex = clientID;
  return HostIndex;
}

int _Host()
{
  typedef DWORD (*plAyerState_t)(int clientNum);
  plAyerState_t plAyerState = (plAyerState_t)0x821E66A8;
  DWORD ps;
  for( int clientID = 0; clientID < 18; clientID++)
  {
    ps = plAyerState(clientID);
    ps += 0x44;
    strcpy(CurrentGamertag[clientID], (char*)ps);
  }
  return FindHost();
}

bool gtnw()
{
    return stricmp(gametype, "gtnw") == 0?true:false;
}

namespace models
{
    typedef int (__cdecl * G_GetModelIndex_t)(char *Model);
    G_GetModelIndex_t G_GetModelIndex = (G_GetModelIndex_t)0x8220CAD8;

    typedef void (__cdecl * SV_LinkEntity_t)(DWORD entity);
    SV_LinkEntity_t SV_LinkEntity = (SV_LinkEntity_t)0x8225F588;
     
    typedef void (__cdecl * SV_UnlinkEntity_t)(DWORD entity);
    SV_UnlinkEntity_t SV_UnlinkEntity = (SV_UnlinkEntity_t)0x8225F4A0;
     
    typedef void (__cdecl * SV_SetBrushModel_t)(DWORD entity);
    SV_SetBrushModel_t SV_SetBrushModel = (SV_SetBrushModel_t)0x82254BB8;

    typedef  void (__cdecl * SP_script_model_t)(int pSelf);
    SP_script_model_t SP_script_model = (SP_script_model_t)(0x82206E20);

    typedef int (__cdecl * G_Spawn_t)();
    G_Spawn_t G_Spawn = (G_Spawn_t)(0x8220DBE8);

    typedef void (__cdecl * G_SetModel_t)(int ent, const char *modelName);
    G_SetModel_t G_SetModel = (G_SetModel_t)(0x8220D310);
     
    void CloneBrushModelToScriptModel(DWORD ScriptModel, DWORD BrushModel)
    {
        SV_UnlinkEntity(ScriptModel);
        *(byte *)(ScriptModel + 0x101) = 0x04;
        *(int *)(ScriptModel + 0x88) = *(int *)(BrushModel + 0x88);
        int flag = *(int *)(ScriptModel + 0x11C);
        SV_SetBrushModel(ScriptModel);
        flag |= *(int *)(ScriptModel + 0x11C);
        *(int *)(ScriptModel + 0x11C) = flag;
        SV_LinkEntity(ScriptModel);
    }
    
    void Spawn_Model(const char* Model, float X, float Y, float Z)
    {
        int temp = G_Spawn();
        G_SetModel(temp,Model);
        *(float*)(temp + 0x138) = X;
        *(float*)(temp + 0x13C) = Y;
        *(float*)(temp + 0x140) = Z;
        SP_script_model(temp);
    }
};

bool in_array(const string &needle, const vector< string > &haystack)
{
    int max=haystack.size();

    if (max==0) return false;

    for(int i=0; i<max; i++)
        if (haystack[i]==needle)
            return true;
    return false;
}

bool map(char *map)
{
    if(stricmp(Dvar_GetString("ui_mapname"), map) == 0)
        return true;
    else
        return false;
}

typedef void (*XNotifyQueueUI)(u64 stringId, u64 playerIndex, u64 r5, WCHAR* displayText, u64 r7); 

char *onoff(bool on)
{
    if(on)
        return "^7[^2ON^7]";
    else
        return "^7[^1OFF^7]";
}

void ThreadMe(HANDLE handle, DWORD lpThreadId, __in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter=NULL)
{
        handle = CreateThread(NULL, NULL, lpStartAddress, lpParameter, 0x2, &lpThreadId); 
        SetThreadPriority(handle, THREAD_BASE_PRIORITY_IDLE);
        ResumeThread(handle);
}

char* cp(char* Text, ...)
{
    static CHAR buffer[0x2000];
    va_list pArgList;
    va_start(pArgList, Text);
    vsprintf(buffer, Text, pArgList);
    return buffer;
    RtlZeroMemory(buffer, sizeof(buffer));
	//XPhysicalFree(buffer);
}

void CleanEntry()
{
  hasRan = false;
  DWORD ExitCode;
  if (GetExitCodeThread(hThreadMain,&ExitCode) != 0)
  {
     DbgPrint("Main thread killed - ");
     ExitThread(ExitCode);  
  }
}

void dumpTemps()
{
    smc Console;
    DbgPrint("CPU Temp: %f\n", Console.GetTemperature(CPU, true));
    DbgPrint("GPU Temp: %f\n", Console.GetTemperature(GPU, true));
    DbgPrint("MEM Temp: %f\n", Console.GetTemperature(MEM, true));
    DbgPrint("CASE Temp: %f\n", Console.GetTemperature(BRD, true));
}

#define __isync() __emit(0x4C00012C)

#define doSync(addr) \
do { \
__dcbst(0, addr); \
__sync(); \
__isync(); \
} while (0)

VOID addresshook(PDWORD addr, DWORD dest, BOOL linked)
{
    if(dest & 0x8000) // If bit 16 is 1
     addr[0] = 0x3D600000 + (((dest >> 16) & 0xFFFF) + 1); // lis %r11, dest>>16 + 1
    else
     addr[0] = 0x3D600000 + ((dest >> 16) & 0xFFFF); // lis %r11, dest>>16

     addr[1] = 0x396B0000 + (dest & 0xFFFF); // addi %r11, %r11, dest&0xFFFF
     addr[2] = 0x7D6903A6; // mtctr %r11

    if(linked)
     addr[3] = 0x4E800421; // bctrl
    else
     addr[3] = 0x4E800420; // bctr

     doSync(addr);
}

UINT32 resolveFunct(char* modname, UINT32 ord)
{
        UINT32 ptr32 = 0, ret = 0, ptr2 = 0;
        ret = XexGetModuleHandle(modname, (PHANDLE)&ptr32);
        if(ret == 0){
                ret = XexGetProcedureAddress((HANDLE)ptr32, ord, &ptr2);
                if(ptr2 != 0)
                        return(ptr2);
        }
        return(0);
} 

void Popup(LPCWSTR Message, byte icon)
{
  XNotifyQueueUI xNotifyQueueUI = (XNotifyQueueUI)resolveFunct("xam.xex", 656);
  WCHAR buffer[0x256];
  swprintf(buffer, Message);
  xNotifyQueueUI(icon, 0x0, 2, buffer, 0); 
}

void doFuckoff()
{
    smc Console;
    Console.SetLEDS(RED, RED, RED, RED);
    Console.SetPowerLED(POWER_LED_BLINK, true);
    Popup(L"iKonroi V4 - You must be online to use this DLL, fuckoff!", 16); 
    typedef void (*EndGame_t)(void);
    EndGame_t EndGame = (EndGame_t)0x82201A48;
    EndGame();
}

void failedAuth(LPCWSTR msg)
{
    smc Console;
    Console.SetPowerLED(POWER_LED_BLINK, true);
    Console.SetLEDS(RED, RED, RED, RED);
    Popup(msg, 16);
    Sleep(2000);
    BYTE code[4] = { 0x82, 0x04, 0x31, 0x00 };
    HalSendSMCMessage(code, NULL);
}

 __int64 __declspec(naked) HvxPeekCall(DWORD key, __int64 type, __int64 SourceAddress, __int64 DestAddress, __int64 lenInBytes)
{
    __asm
    {
            li r0, 0x0
            sc
            blr
    }
}

bool Authed()
{
	//%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X
	//%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02XF%02X
    time_t theTime = time(NULL);
    struct tm *Time = localtime(&theTime);
    char CPUBuff[0x32]; 
	char CPUArrayBuff[0x3];                               
    BYTE HVBuffer[0x10];


    HvxPeekCall(0x72627472, 5, 0x20, (__int64)0x8000000000000000ULL | ((DWORD)MmGetPhysicalAddress(HVBuffer, 0x1)&0xFFFFFFFF), 0x10);
    memcpy(CPUArrayBuff, HVBuffer, 0x10);
    sprintf(
     CPUBuff, "%97X%DCX%EBX%CAX%94X%7BX%31X%02X%86X%ADX%06X%8CX%C7X%A3X%A8X%50X",
     CPUArrayBuff[0], CPUArrayBuff[1], CPUArrayBuff[2], CPUArrayBuff[3],
     CPUArrayBuff[4], CPUArrayBuff[5], CPUArrayBuff[6], CPUArrayBuff[7],
     CPUArrayBuff[8], CPUArrayBuff[9], CPUArrayBuff[10], CPUArrayBuff[11],
     CPUArrayBuff[12], CPUArrayBuff[13], CPUArrayBuff[14], CPUArrayBuff[15],														
     CPUArrayBuff[16]
    );
	printf("%s\n",CPUBuff);
    if(stricmp(CPUBuff, "97DCEBCA947B310286AD068CC7A3A850")==0)
        if(Time->tm_year + 1900 == (int)2013 && Time->tm_mon + 1 == (int)9 && Time->tm_mday < (int)25)
            return true;
		else {failedAuth(L"if you see this contact moxhification #3"); return false;}
	else {failedAuth(L"if you see this contact moxhification #2"); return false;}
    return false;
}

void auth()
{
    smc Console;
    char RealGT[0x16];
    while(XUserGetSigninState(0) == eXUserSigninState_NotSignedIn)
    {
        Sleep(1000);
        XShowSigninUI(0, XSSUI_FLAGS_DISALLOW_PLAYAS);
		Popup(L"if you see this contact moxhification #1", 16);
    }
    XUserGetName(NULL, RealGT, NULL);
    wchar_t final[0x37];
    char msg[0x37];
    sprintf(msg, "Welcome %s to Moxhification v2", RealGT);
    mbstowcs(final, msg, strlen(msg)+1);//Plus null
    Popup(final, 14);
    Console.SetFanSpeed(1, 75);
    Console.SetFanSpeed(2, 75);
    Sleep(100);
    Console.SetLEDS(RED, RED, RED, RED);
    Sleep(500);
    Console.SetLEDS(ORANGE, ORANGE, ORANGE, ORANGE);
    Sleep(500);
    Console.SetLEDS(GREEN, GREEN, GREEN, GREEN);
    Sleep(500);
    Console.SetLEDS(RED, OFF, OFF, OFF);
    char buffer[100];
    sprintf(buffer, "%s\n^81.4", "iKonroi V5");
    strcpy((char*)(0x82922FA0), buffer);
    Console.SetPowerLED(POWER_LED_ON, true);
}