#include"Triangle.h"
bool InsertTriangleHook()
{
  for (DWORD i = processStartAddress; i < processStopAddress - 4; i++){
    DWORD j=0;
    if ((*(DWORD *)i & 0xffffff) == 0x75403c){
      j=i + 4 + *(BYTE*)(i+3);
    }
    else if((*(DWORD *)i & 0xffffffff) == 0x850f403c)  
      //长跳转
      //エグゼクタースクリプト
      j = i + 4 + *(int*)(i+4);
    
    if(j){
      for (DWORD k = j + 0x20; j < k; j++)
        if (*(BYTE*)j == 0xe8) {
          DWORD t = j + 5 + *(DWORD *)(j + 1);
          if (t > processStartAddress && t < processStopAddress) {
            HookParam hp;
            hp.address = t;
            hp.offset=get_stack(1);
            hp.type = USING_STRING;
            ConsoleOutput("INSERT Triangle");
            return NewHook(hp, "Triangle");
          }
        }
    }
  }
     
  //ConsoleOutput("Old/Unknown Triangle engine.");
  ConsoleOutput("Triangle: failed");
  return false;
}


bool Triangle::attach_function() { 
    return InsertTriangleHook();
} 

bool InsertTrianglePixHook() 
{
  
    /*
    * Sample games:
    * https://vndb.org/v38070
    * https://vndb.org/v42090
    * https://vndb.org/v41025
    */
  const BYTE bytes[] = {
    0x50,                      // push eax           << hook here
    0xE8, XX4,                 // call FinalIgnition.exe+4DE10
    0x8B, 0x83, XX4,           // mov eax,[ebx+0000DCA0]
    0x8D, 0x8D, XX4,           // lea ecx,[ebp-0000022C]
    0x83, 0x7D, 0x44, 0x10,    // cmp dword ptr [ebp+44],10
    0xFF, 0x75, 0x40           // push [ebp+40]
  };

  ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
  ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
  if (!addr) return false; 

  HookParam hp;
  hp.address = addr;
  hp.offset=get_reg(regs::eax);
  hp.index = 0;
  hp.type = CODEC_UTF8 | USING_STRING | NO_CONTEXT;
  hp.filter_fun = NewLineCharToSpaceFilterA;
  return NewHook(hp, "TrianglePix");
}
bool Triangle2_attach_function(){
  const BYTE bytes[] = {
      0x0f,0x57,XX,
      0x68,0x0F,0x27,0x00,0x00,
      0x0f,0x57,XX
    };
    auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
    ConsoleOutput("%p", addr);
    if (addr == 0)return false; 
    addr = MemDbg::findEnclosingAlignedFunction(addr);
    ConsoleOutput("%p", addr);
    if (addr == 0)return false;
    HookParam hp;
    hp.address = addr;
    hp.offset=get_stack(5);
    hp.type = USING_STRING|CODEC_UTF8|NO_CONTEXT; 
    return NewHook(hp, "triangle");
}
bool Triangle2::attach_function(){
  return Triangle2_attach_function()||InsertTrianglePixHook();
}
bool TriangleM1(){
  auto _=L"${FirstName}";
  ULONG addr = MemDbg::findBytes(_, sizeof(_), processStartAddress, processStopAddress);
  if (!addr) return false; 
   
  BYTE pushoffset[]={0x68,XX4};
  *(DWORD*)(pushoffset+1)=addr;
  addr = MemDbg::findBytes(pushoffset, sizeof(pushoffset), processStartAddress, processStopAddress);
  if (!addr) return false;  
  addr = MemDbg::findEnclosingAlignedFunction(addr);
  if (addr == 0)return false;
  HookParam hp;
  hp.address = addr;
  hp.offset=get_stack(2);
  hp.type = USING_STRING|CODEC_UTF16; 
  return NewHook(hp, "TriangleM");
}
bool TriangleM2(){
  BYTE _[]={0x33,0xff,0x66,0x39,0x3b,0x74};
  ULONG addr = MemDbg::findBytes(_, sizeof(_), processStartAddress, processStopAddress);
  if (!addr) return false;  
  HookParam hp;
  hp.address = addr;
  hp.offset=get_reg(regs::ebx);
  hp.type = USING_STRING|CODEC_UTF16|NO_CONTEXT; 
  return NewHook(hp, "TriangleM");
}
bool TriangleM::attach_function(){
  //蛇香のライラ ~Allure of MUSK~ 第一夜 ヨーロピアン・ナイト 体験版
  auto _1=TriangleM1();
  auto _2=TriangleM2();
  return _1||_2;
}