#include"Lucifen.h"
 #include"embed_util.h"
/********************************************************************************************
Lucifen hook:
  Game folder contains *.lpk. Used by Navel games.
  Hook is same to GetTextExtentPoint32A, use ESP to split name.
********************************************************************************************/
bool InsertLucifenHook()
{
  // BOOL GetTextExtentPoint32(
  //   _In_   HDC hdc,
  //   _In_   LPCTSTR lpString,
  //   _In_   int c,
  //   _Out_  LPSIZE lpSize
  // );
  HookParam hp;
  hp.address = (DWORD)::GetTextExtentPoint32A;
  hp.offset=get_stack(2); // arg2 lpString
  hp.split = get_reg(regs::esp);
  hp.length_offset = 3;
  hp.type = USING_STRING|USING_SPLIT;
  ConsoleOutput("INSERT Lucifen");
  return NewHook(hp, "Lucifen");
  //RegisterEngineType(ENGINE_LUCIFEN);
}
namespace{
  bool hook(){ 
    //まじかるカナン -RISEA-
    auto oldoutline=(ULONG)GetProcAddress(GetModuleHandle(L"gdi32.dll"),"GetGlyphOutline");
    auto addr=MemDbg::findCallerAddress(oldoutline, 0xec8b55,processStartAddress, processStopAddress); 
    if (addr == 0)
      addr=MemDbg::findCallerAddress((ULONG)GetGlyphOutlineA, 0xec8b55,processStartAddress, processStopAddress); 
    if (addr == 0)
      return false;
    HookParam hp;
    hp.address = addr;
    hp.offset=get_stack(1); 
    hp.split=get_stack(6);
    hp.type = CODEC_ANSI_BE |USING_SPLIT;
    return NewHook(hp, "Lucifen2"); 
  }
}

 bool hookBefore_navel(hook_stack*s,void* data, size_t* len,uintptr_t*role)
  {  
    
      auto text = std::string((char*)s->stack[1]); // text in arg1  
       

      if(text.find("$&")!=text.npos){
          text=text.substr(text.find("$&")+2);
      }
      if(text[text.size()-1]=='$')
        text=text.substr(0,text.size()-1);
       
      write_string_overwrite(data,len,text);
      return true;
  }
 void hookafter_navel(hook_stack*s,void* data, size_t len)
  {  
      auto text = std::string((char*)s->stack[1]); // text in arg1  
      auto split = s->stack[0]; // retaddr 
       
      std::string  newData = std::string((char*)data,len); 

      if(text.find("$&")!=text.npos){ 
          newData=text.substr(0,text.find("$&")+2)+newData;
      }
      if(text[text.size()-1]=='$')
        newData=newData+"$";
       
      strcpy((char*)s->stack[1], newData.c_str());
      //s->stack[1] = (ULONG)newData.data();
  }

bool attach_navel(ULONG startAddress, ULONG stopAddress) // attach scenario
{
// 通过搜索3C 9F(i > 0x9Fu shiftjis范围判断)找到。
//   int __thiscall sub_455AB0(int this, _BYTE *a2)
// {
//   LPCSTR **v2; // ebx
//   int v3; // edi
//   _BYTE *v4; // ebp
//   char v5; // cl
//   _BYTE *v6; // ebx
//   int v7; // esi
//   unsigned __int8 v8; // al
//   char v9; // al
//   const CHAR **v10; // ebx
//   bool v11; // zf
//   const CHAR *v12; // eax
//   unsigned int v13; // esi
//   char *v14; // eax
//   char *v16; // ecx
//   unsigned __int8 v17; // al
//   char v18; // al
//   const CHAR ***v19; // ebp
//   const CHAR *v20; // esi
//   int v21; // eax
//   unsigned __int8 v22; // al
//   char v23; // cl
//   int v24; // esi
//   LPCSTR **j; // ebp
//   char v26; // al
//   LPCSTR **v27; // ebx
//   char v28; // al
//   char v29; // al
//   char v30; // al
//   unsigned int v31; // esi
//   unsigned __int8 *v32; // eax
//   char v33; // al
//   int v34; // eax
//   unsigned __int8 *v35; // ebx
//   unsigned __int8 v36; // al
//   char v37; // al
//   const CHAR ***v38; // ebp
//   const CHAR *v39; // esi
//   int v40; // eax
//   CHAR *v41; // edi
//   char v42; // al
//   unsigned __int8 v43; // al
//   unsigned __int8 v44; // al
//   unsigned __int16 *v45; // ebp
//   unsigned __int16 *v46; // edi
//   unsigned int v47; // eax
//   __int16 v48; // dx
//   unsigned __int16 *v49; // esi
//   unsigned int v51; // [esp+14h] [ebp-4h]
//   char *i; // [esp+1Ch] [ebp+4h]
//   unsigned int v53; // [esp+1Ch] [ebp+4h]

    const uint8_t bytes[] = {
      0x50,
      0xff,0x15,0xfc,0xd0,0x4e,0x00,
      0x03,0xf0,
      0x83,0xc3,0x04,
      0xb1,0x01
    };
    ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
    if (addr == 0)return false;
      
    addr = MemDbg::findEnclosingAlignedFunction(addr);
    if (!addr) return false;
    HookParam hp;
    hp.address = addr; 
    hp.type = EMBED_ABLE|EMBED_DYNA_SJIS;
    hp.hook_before=hookBefore_navel;
    hp.hook_after=hookafter_navel;
    hp.hook_font=F_GetGlyphOutlineA|F_GetTextExtentPoint32A;
    return NewHook(hp, "LucifenEmbed"); 
}
#include"dyncodec/dynsjis.h"
namespace { // unnamed
namespace ScenarioHook {

std::unordered_set<UINT64> textHashes_;

namespace Private {

  ULONG scenarioOffset_,
        nameOffset_;

  std::string replaceNewLines(const std::string &data)
  {
    std::string ret;
    //ret.replace("\n", 1, "\x00\x5b\x0c\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00", 0xc + 2);
    for (auto p = data.c_str(); *p;)
      if (*p == '\n') {
        ret.append("\x00\x5b\x0c\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00", 0xc + 2);
        p++;
      } else {
        ret.push_back(*p++);
        if (*p && dynsjis::isleadbyte(p[-1]))
          ret.push_back(*p++);
      }

    //std::string ret;
    //do {
    //  ret.append(start, p - start);
    //  if (dynsjis::prevchar(p, start) == p - 1) {
    //    ret.append("\x00\x5b\x0c\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00", 0xc + 2);
    //    p++;
    //  } else {
    //    start = p;
    //    p = ::strchr(p, '\n');
    //  }
    //} while (p && *p);
    return ret;
  }

  /**
   *  Sample game: 猫撫ディストーション
   *
   *  0x5b is the text to skip next character
   *
   *  Ruby:
   *  014BB52C  81 77 8C F5 00 5B 1C 00 00 00 1B 00 00 00 01 00  『光.[.......
   *  014BB53C  00 00 03 0B 00 00 00 83 72 83 62 83 4F 83 6F 83  .....ビッグバ・
   *  014BB54C  93 00 81 78 82 CC 91 4F 81 5C 81 5C 00 5B 0C 00  ・』の前――.[..
   *  014BB55C  00 00 0E 00 00 00 00 00 00 00 82 C2 82 DC 82 E8  .........つまり
   *  014BB56C  81 41 89 46 92 88 82 AA 90 B6 82 DC 82 EA 82 E9  、宇宙が生まれる
   *  014BB57C  91 4F 82 A9 82 E7 82 A0 82 C1 82 BD 82 E0 82 CC  前からあったもの
   *  014BB58C  81 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00  。..............
   *  014BB59C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *
   *  No ruby:
   *  014BB52C  82 B6 82 E1 82 A0 81 41 81 77 8C BE 97 74 81 78  じゃあ、『言葉』
   *  014BB53C  82 C1 82 C4 89 BD 82 C8 82 F1 82 BE 81 48 6F 83  って何なんだ?o・
   *  014BB54C  93 00 81 78 82 CC 91 4F 81 5C 81 5C 00 5B 0C 00  ・』の前――.[..
   *  014BB55C  00 00 0E 00 00 00 00 00 00 00 82 C2 82 DC 82 E8  .........つまり
   *  014BB56C  81 41 89 46 92 88 82 AA 90 B6 82 DC 82 EA 82 E9  、宇宙が生まれる
   *  014BB57C  91 4F 82 A9 82 E7 82 A0 82 C1 82 BD 82 E0 82 CC  前からあったもの
   *  014BB58C  81 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00  。..............
   *  014BB59C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5AC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5BC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5CC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *
   *  014BB52C  96 85 82 CC 8B D5 00 5B 16 00 00 00 1B 00 00 00  妹の琴.[......
   *  014BB53C  01 00 00 00 03 05 00 00 00 82 B1 82 C6 00 8E 71  ......こと.子
   *  014BB54C  00 5B 14 00 00 00 1B 00 00 00 01 00 00 00 03 03  .[.........
   *  014BB55C  00 00 00 82 B1 00 82 CD 82 BB 82 A4 8C BE 82 C1  ...こ.はそう言っ
   *  014BB56C  82 BD 81 42 82 C6 82 A2 82 A4 88 D3 96 A1 82 F0  た。という意味を
   *  014BB57C  97 5E 82 A6 82 BD 82 CC 81 76 82 BD 82 E0 82 CC  与えたの」たもの
   *  014BB58C  81 42 00 00 00 00 00 00 00 00 00 00 00 00 00 00  。..............
   *  014BB59C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5AC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5BC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014BB5CC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *
   *  New line:
   *  014D7D39  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7D49  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7D59  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7D69  00 00 00 00 00 01 00 E6 01 00 00 54 01 00 00 00  ......・..T...
   *  014D7D79  00 00 00 B0 11 52 00 D8 CD 4D 01 44 EE E9 07 D8  ...ーR.リヘMD鵫リ
   *  014D7D89  CD 4D 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ヘM.............
   *  014D7D99  00 00 00 F0 50 4E 01 0C 53 4E 01 F0 54 4E 01 10  ...N.SNN
   *  014D7DA9  00 00 00 00 00 00 00 82 BB 82 B5 82 C4 89 B4 82  .......そして俺・
   *  014D7DB9  C9 82 E0 81 41 00 5B 0C 00 00 00 0E 00 00 00 00  ノも、.[........
   *  014D7DC9  00 00 00 90 7E 96 5B 82 CC 82 B1 82 EB 82 A9 82  ...厨房のころか・
   *  014D7DD9  E7 8E 6C 94 4E 8A D4 81 41 96 88 93 FA 91 B1 82  邇l年間、毎日続・
   *  014D7DE9  AF 82 C4 82 A2 82 E9 82 B1 82 C6 82 AA 82 A0 82  ッていることがあ・
   *  014D7DF9  E9 81 42 00 00 00 00 00 00 00 00 00 00 00 00 00  驕B.............
   *  014D7E09  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E19  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E29  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E39  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E49  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E59  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E69  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E79  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E89  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   *  014D7E99  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
   */
  template <typename strT>
  strT ltrimScenarioText(strT p)
  {
    while (p[0] == 0 && p[1] == 0x5b && p[2] > 0)
      p += p[2] + 2;
    return p;
  }
  std::string parseScenarioText(const char *p, const char *end)
  {
    int size = ::strlen(p);
    if (end > p && end - p < size)
      size = end - p;
    std::string ret;
    if (size)
      ret=std::string(p, size);
    //if ((uint8_t)p[ret.size() - 1] == 0x93 && (uint8_t)p[ret.size() - 1] == 0x83)// trim encindg \x83\x93
    //  return ret.left(ret.size() - 2);
    for (p += ret.size(); (!end || p < end) && p[1] == 0x5b && p[2] > 0; p += ret.size()) {
      //if (p[2] == 0xc && p[6] == 0xe) {
      //  ret.push_back('\n');
      //  ret.push_back('\n'); // insert double new lines
      //}
      p += p[2] + 2;
      size = ::strlen(p);
      if (end > p && end - p < size)
        size = end - p;
      ret.append(p, size);
    }
    return ret;
  }

  bool dispatchNameText(char *text, ULONG split,hook_stack*s,void* data, size_t* len1,uintptr_t*role)
  {
    enum { capacity = 0x10 }; // excluding '\0'
    *role = Engine::NameRole ;

    if (!*text)
      return false;
 
    write_string_overwrite(data,len1,text);
    return true;
  }

  bool dispatchScenarioText(char *text, ULONG split,hook_stack*s,void* data, size_t* len1,uintptr_t*role)
  {
    // text[0] could be \0
    * role = Engine::ScenarioRole ;
    auto scenarioEndAddress = (LPSTR *)(text + 0x1000);
    auto scenarioEnd = *scenarioEndAddress;
    if (!Engine::isAddressReadable(scenarioEnd))
      scenarioEnd = nullptr;
      //DOUT("warning: scenario end NOT FOUND");
 

    text = ltrimScenarioText(text);
    if (!*text)
      return false;
    std::string oldData = parseScenarioText(text, scenarioEnd);
    write_string_overwrite(data,len1,oldData);
    return true;
  }
bool dispatchNameTextafter(char *text, ULONG split,hook_stack*s,void* data, uintptr_t  len1 )
  {
    std::string oldData = text;
     auto newData=std::string((char*)data,len1);
     enum { capacity = 0x10 }; // excluding '\0'
    int size = newData.size();
    if (size > capacity)
      size = capacity;
    else if (size < oldData.size())
      ::memset(text + size, 0, oldData.size() - size);

    ::memcpy(text, newData.c_str(), size);
    return true;
  }

  void dispatchScenarioTextafter(char *text, ULONG split,hook_stack*s,void* data, uintptr_t len1 )
  { 
    auto scenarioEndAddress = (LPSTR *)(text + 0x1000);
    auto scenarioEnd = *scenarioEndAddress;
    if (!Engine::isAddressReadable(scenarioEnd))
      scenarioEnd = nullptr;
      //DOUT("warning: scenario end NOT FOUND");
 
    text = ltrimScenarioText(text);
    if (!*text)
      return;
    std::string oldData = parseScenarioText(text, scenarioEnd);
    auto newData=std::string((char*)data,len1);
    if (newData.empty() || newData == oldData)
      return;

    if (newData.find('\n')!=newData.npos)
      newData = replaceNewLines(newData);

    if (scenarioEnd > text && scenarioEnd - text > newData.size())
      ::memset(text + newData.size(), 0, scenarioEnd - text - newData.size());
    else if (oldData.size() > newData.size())
      ::memset(text + newData.size(), 0, oldData.size() - newData.size());

    //::strcpy(text, newData.constData());
    ::memcpy(text, newData.c_str(), newData.size() + 1);

    *scenarioEndAddress = text + newData.size(); // FIXME: THis sometimes does not work
  }
  bool hookBefore(hook_stack*s,void* data, size_t* len1,uintptr_t*role)
  {
    auto self = (LPSTR)s->ecx;
    ULONG retaddr = s->stack[0];
  //  bool b1=  dispatchNameText(self + nameOffset_, retaddr,s,data,len1,role);
    bool b2=dispatchScenarioText(self + scenarioOffset_, retaddr,s,data,len1,role);
    return  b2;
  }
    void hookafter(hook_stack*s,void* data, uintptr_t len1)
  {
    auto self = (LPSTR)s->ecx;
    ULONG retaddr = s->stack[0];
   //  dispatchNameTextafter(self + nameOffset_, retaddr,s,data,len1);
     dispatchScenarioTextafter(self + scenarioOffset_, retaddr,s,data,len1); 
  }
} // namespace Private

/**
 *  Debugging method:
 *  - Hijack GetGlyphOutlineA
 *    There is only one GetGlyphOutlineA
 *  - Find all text in memory
 *    There are two matches.
 *    One is current text with fixed address
 *    One is all text with fixed address
 *  - Find all text address on the stack
 *    There is one function use it as arg1 and as future text
 *    ecx is the current text instead
 *
 *  Sample game: プリズム・プリンセス
 *  name = ecx + 0xadd1
 *  scenario = ecx + 0xae48
 *  scenario end = ecx + 0xbe48
 *
 *  00441E3F   90               NOP
 *  00441E40   83EC 1C          SUB ESP,0x1C
 *  00441E43   53               PUSH EBX
 *  00441E44   56               PUSH ESI
 *  00441E45   8BF1             MOV ESI,ECX
 *  00441E47   8B9E 48BE0000    MOV EBX,DWORD PTR DS:[ESI+0xBE48]
 *  00441E4D   2BDE             SUB EBX,ESI
 *  00441E4F   81EB 48AE0000    SUB EBX,0xAE48
 *  00441E55   75 0B            JNZ SHORT .00441E62
 *  00441E57   5E               POP ESI
 *  00441E58   B8 01000000      MOV EAX,0x1
 *  00441E5D   5B               POP EBX
 *  00441E5E   83C4 1C          ADD ESP,0x1C
 *  00441E61   C3               RETN
 *  00441E62   8B86 AC040000    MOV EAX,DWORD PTR DS:[ESI+0x4AC]
 *  00441E68   55               PUSH EBP
 *  00441E69   57               PUSH EDI
 *  00441E6A   50               PUSH EAX
 *  00441E6B   8BCE             MOV ECX,ESI
 *  00441E6D   E8 9E6CFFFF      CALL .00438B10
 *  00441E72   8A96 DE050000    MOV DL,BYTE PTR DS:[ESI+0x5DE]
 *  00441E78   8B8E 909E0000    MOV ECX,DWORD PTR DS:[ESI+0x9E90]
 *  00441E7E   8BBE 489E0000    MOV EDI,DWORD PTR DS:[ESI+0x9E48]
 *  00441E84   84D2             TEST DL,DL
 *  00441E86   0F94C0           SETE AL
 *  00441E89   84C0             TEST AL,AL
 *  00441E8B   884424 13        MOV BYTE PTR SS:[ESP+0x13],AL
 *  00441E8F   C741 20 00000000 MOV DWORD PTR DS:[ECX+0x20],0x0
 *  00441E96   74 0D            JE SHORT .00441EA5
 *  00441E98   8BCE             MOV ECX,ESI
 *
 *  00441E9A   E8 4136FFFF      CALL .004354E0
 *  00441E9F   8987 A8030000    MOV DWORD PTR DS:[EDI+0x3A8],EAX
 *  00441EA5   8D86 48AE0000    LEA EAX,DWORD PTR DS:[ESI+0xAE48]	; jichi: this is the scenari text
 *  00441EAB   53               PUSH EBX
 *  00441EAC   50               PUSH EAX
 *  00441EAD   8BCF             MOV ECX,EDI
 *  00441EAF   E8 EC6B0000      CALL .00448AA0
 *  00441EB4   8D9E E2AD0000    LEA EBX,DWORD PTR DS:[ESI+0xADE2]	; jichi: this is the character name
 *  00441EBA   8D86 D1AD0000    LEA EAX,DWORD PTR DS:[ESI+0xADD1]	; jichi: this is the name text
 *  00441EC0   53               PUSH EBX
 *  00441EC1   50               PUSH EAX
 *  00441EC2   8BCF             MOV ECX,EDI
 *  00441EC4   894424 1C        MOV DWORD PTR SS:[ESP+0x1C],EAX
 *  00441EC8   E8 836B0000      CALL .00448A50
 *
 *  00441ECD   8A4424 13        MOV AL,BYTE PTR SS:[ESP+0x13]
 *  00441ED1   84C0             TEST AL,AL
 *  00441ED3   74 30            JE SHORT .00441F05
 *  00441ED5   6A 01            PUSH 0x1
 *  00441ED7   8BCF             MOV ECX,EDI
 *  00441ED9   E8 726D0000      CALL .00448C50
 *  00441EDE   803B 00          CMP BYTE PTR DS:[EBX],0x0
 *  00441EE1   74 22            JE SHORT .00441F05
 *  00441EE3   8B86 00AE0000    MOV EAX,DWORD PTR DS:[ESI+0xAE00]
 *  00441EE9   85C0             TEST EAX,EAX
 *  00441EEB   75 18            JNZ SHORT .00441F05
 *  00441EED   8B86 AC040000    MOV EAX,DWORD PTR DS:[ESI+0x4AC]
 *  00441EF3   8D97 D1030000    LEA EDX,DWORD PTR DS:[EDI+0x3D1]
 *  00441EF9   8996 00AE0000    MOV DWORD PTR DS:[ESI+0xAE00],EDX
 *  00441EFF   8986 C0040000    MOV DWORD PTR DS:[ESI+0x4C0],EAX
 *  00441F05   8A86 30A60000    MOV AL,BYTE PTR DS:[ESI+0xA630]
 *  00441F0B   84C0             TEST AL,AL
 *  00441F0D   0F84 DB000000    JE .00441FEE
 *  00441F13   8B86 C0A00000    MOV EAX,DWORD PTR DS:[ESI+0xA0C0]
 *  00441F19   85C0             TEST EAX,EAX
 *  00441F1B   0F84 CD000000    JE .00441FEE
 *  00441F21   8B96 E0A00000    MOV EDX,DWORD PTR DS:[ESI+0xA0E0]
 *  00441F27   8DAE E0A00000    LEA EBP,DWORD PTR DS:[ESI+0xA0E0]
 *  00441F2D   6A 00            PUSH 0x0
 *  00441F2F   8BCD             MOV ECX,EBP
 *  00441F31   FF92 B4000000    CALL DWORD PTR DS:[EDX+0xB4]
 *  00441F37   8B86 489E0000    MOV EAX,DWORD PTR DS:[ESI+0x9E48]
 *  00441F3D   8D8E 5C470000    LEA ECX,DWORD PTR DS:[ESI+0x475C]
 *  00441F43   8D96 14680000    LEA EDX,DWORD PTR DS:[ESI+0x6814]
 *  00441F49   898E E4050000    MOV DWORD PTR DS:[ESI+0x5E4],ECX
 *  00441F4F   894424 18        MOV DWORD PTR SS:[ESP+0x18],EAX
 *  00441F53   89AE 489E0000    MOV DWORD PTR DS:[ESI+0x9E48],EBP
 *  00441F59   C686 D8A00000 01 MOV BYTE PTR DS:[ESI+0xA0D8],0x1
 *  00441F60   8996 E8050000    MOV DWORD PTR DS:[ESI+0x5E8],EDX
 *  00441F66   8B87 B4030000    MOV EAX,DWORD PTR DS:[EDI+0x3B4]
 *  00441F6C   6A 01            PUSH 0x1
 *  00441F6E   8D4C24 20        LEA ECX,DWORD PTR SS:[ESP+0x20]
 *  00441F72   6A 01            PUSH 0x1
 *  00441F74   51               PUSH ECX
 *  00441F75   50               PUSH EAX
 *  00441F76   8BCD             MOV ECX,EBP
 *  00441F78   E8 935D0000      CALL .00447D10
 *  00441F7D   8B5424 18        MOV EDX,DWORD PTR SS:[ESP+0x18]
 *  00441F81   8D8E EC050000    LEA ECX,DWORD PTR DS:[ESI+0x5EC]
 *  00441F87   8996 489E0000    MOV DWORD PTR DS:[ESI+0x9E48],EDX
 *  00441F8D   8D96 A4260000    LEA EDX,DWORD PTR DS:[ESI+0x26A4]
 *  00441F93   85C0             TEST EAX,EAX
 *  00441F95   C686 D8A00000 00 MOV BYTE PTR DS:[ESI+0xA0D8],0x0
 *  00441F9C   898E E4050000    MOV DWORD PTR DS:[ESI+0x5E4],ECX
 *  00441FA2   8996 E8050000    MOV DWORD PTR DS:[ESI+0x5E8],EDX
 *  00441FA8   7E 44            JLE SHORT .00441FEE
 *  00441FAA   8A86 31A60000    MOV AL,BYTE PTR DS:[ESI+0xA631]
 *  00441FB0   84C0             TEST AL,AL
 *  00441FB2   74 0A            JE SHORT .00441FBE
 *  00441FB4   33C0             XOR EAX,EAX
 *  00441FB6   8A86 32A60000    MOV AL,BYTE PTR DS:[ESI+0xA632]
 *  00441FBC   EB 02            JMP SHORT .00441FC0
 *  00441FBE   33C0             XOR EAX,EAX
 *  00441FC0   8B4C24 28        MOV ECX,DWORD PTR SS:[ESP+0x28]
 *  00441FC4   8B6C24 20        MOV EBP,DWORD PTR SS:[ESP+0x20]
 *  00441FC8   8B97 B8030000    MOV EDX,DWORD PTR DS:[EDI+0x3B8]
 *  00441FCE   50               PUSH EAX
 *  00441FCF   8B4424 18        MOV EAX,DWORD PTR SS:[ESP+0x18]
 *  00441FD3   2BCD             SUB ECX,EBP
 *  00441FD5   53               PUSH EBX
 *  00441FD6   83C1 04          ADD ECX,0x4
 *  00441FD9   50               PUSH EAX
 *  00441FDA   8B87 B4030000    MOV EAX,DWORD PTR DS:[EDI+0x3B4]
 *  00441FE0   51               PUSH ECX
 *  00441FE1   52               PUSH EDX
 *  00441FE2   50               PUSH EAX
 *  00441FE3   8D8E B8A00000    LEA ECX,DWORD PTR DS:[ESI+0xA0B8]
 *  00441FE9   E8 72290000      CALL .00444960
 *  00441FEE   8B4C24 14        MOV ECX,DWORD PTR SS:[ESP+0x14]
 *  00441FF2   8D86 48AE0000    LEA EAX,DWORD PTR DS:[ESI+0xAE48]
 *  00441FF8   5F               POP EDI
 *  00441FF9   8986 48BE0000    MOV DWORD PTR DS:[ESI+0xBE48],EAX
 *  00441FFF   5D               POP EBP
 *  00442000   C603 00          MOV BYTE PTR DS:[EBX],0x0
 *  00442003   5E               POP ESI
 *  00442004   C601 00          MOV BYTE PTR DS:[ECX],0x0
 *  00442007   33C0             XOR EAX,EAX
 *  00442009   5B               POP EBX
 *  0044200A   83C4 1C          ADD ESP,0x1C
 *  0044200D   C3               RETN
 *  0044200E   90               NOP
 *  0044200F   90               NOP
 *
 *  Sample game: 猫撫ディストーション
 *  name = ecx + 0xc60f
 *  scenario = ecx + 0xc684
 *  scenario end = ecx + 0xd684
 *
 *  0043E11E   90               NOP
 *  0043E11F   90               NOP
 *  0043E120   83EC 18          SUB ESP,0x18
 *  0043E123   53               PUSH EBX
 *  0043E124   55               PUSH EBP
 *  0043E125   56               PUSH ESI
 *  0043E126   8BF1             MOV ESI,ECX
 *  0043E128   57               PUSH EDI
 *  0043E129   8BAE 84D60000    MOV EBP,DWORD PTR DS:[ESI+0xD684]	; jichi: overall offset is around 0xD684
 *  0043E12F   2BEE             SUB EBP,ESI
 *  0043E131   81ED 84C60000    SUB EBP,0xC684
 *  0043E137   896C24 10        MOV DWORD PTR SS:[ESP+0x10],EBP
 *  0043E13B   75 0D            JNZ SHORT .0043E14A
 *  0043E13D   5F               POP EDI
 *  0043E13E   5E               POP ESI
 *  0043E13F   5D               POP EBP
 *  0043E140   B8 01000000      MOV EAX,0x1
 *  0043E145   5B               POP EBX
 *  0043E146   83C4 18          ADD ESP,0x18
 *  0043E149   C3               RETN
 *  0043E14A   8B86 A8040000    MOV EAX,DWORD PTR DS:[ESI+0x4A8]
 *  0043E150   8BCE             MOV ECX,ESI
 *  0043E152   50               PUSH EAX
 *  0043E153   E8 3875FFFF      CALL .00435690
 *  0043E158   8B9E F4B20000    MOV EBX,DWORD PTR DS:[ESI+0xB2F4]
 *  0043E15E   8BBE D8B10000    MOV EDI,DWORD PTR DS:[ESI+0xB1D8]
 *  0043E164   8B43 14          MOV EAX,DWORD PTR DS:[EBX+0x14]
 *  0043E167   85C0             TEST EAX,EAX
 *  0043E169   7D 7C            JGE SHORT .0043E1E7
 *  0043E16B   8B8E 70040000    MOV ECX,DWORD PTR DS:[ESI+0x470]
 *  0043E171   6A 00            PUSH 0x0
 *  0043E173   8D96 20C60000    LEA EDX,DWORD PTR DS:[ESI+0xC620]	; jichi: 0xc620 is the nearest position
 *  0043E179   6A 00            PUSH 0x0
 *  0043E17B   52               PUSH EDX
 *  0043E17C   6A FE            PUSH -0x2
 *  0043E17E   E8 ED93FEFF      CALL .00427570
 *  0043E183   8BE8             MOV EBP,EAX
 *  0043E185   85ED             TEST EBP,EBP
 *  0043E187   7C 0D            JL SHORT .0043E196
 *  0043E189   45               INC EBP
 *  0043E18A   83FD 08          CMP EBP,0x8
 *  0043E18D   7C 09            JL SHORT .0043E198
 *  0043E18F   BD 07000000      MOV EBP,0x7
 *  0043E194   EB 02            JMP SHORT .0043E198
 *  0043E196   33ED             XOR EBP,EBP
 *  0043E198   396B 1C          CMP DWORD PTR DS:[EBX+0x1C],EBP
 *  0043E19B   74 46            JE SHORT .0043E1E3
 *  0043E19D   8B8F 4C020000    MOV ECX,DWORD PTR DS:[EDI+0x24C]
 *  0043E1A3   85C9             TEST ECX,ECX
 *  0043E1A5   75 0D            JNZ SHORT .0043E1B4
 *  0043E1A7   5F               POP EDI
 *  0043E1A8   5E               POP ESI
 *  0043E1A9   5D               POP EBP
 *  0043E1AA   B8 02000000      MOV EAX,0x2
 *  0043E1AF   5B               POP EBX
 *  0043E1B0   83C4 18          ADD ESP,0x18
 *  0043E1B3   C3               RETN
 *  0043E1B4   8BC5             MOV EAX,EBP
 *  0043E1B6   6A 00            PUSH 0x0
 *  0043E1B8   C1E0 04          SHL EAX,0x4
 *  0043E1BB   03C5             ADD EAX,EBP
 *  0043E1BD   6A 00            PUSH 0x0
 *  0043E1BF   6A 00            PUSH 0x0
 *  0043E1C1   6A 00            PUSH 0x0
 *  0043E1C3   8D94C6 48BA0000  LEA EDX,DWORD PTR DS:[ESI+EAX*8+0xBA48]
 *  0043E1CA   52               PUSH EDX
 *  0043E1CB   E8 E0DD0200      CALL .0046BFB0
 *  0043E1D0   896B 1C          MOV DWORD PTR DS:[EBX+0x1C],EBP
 *  0043E1D3   8B07             MOV EAX,DWORD PTR DS:[EDI]
 *  0043E1D5   6A 01            PUSH 0x1
 *  0043E1D7   6A 01            PUSH 0x1
 *  0043E1D9   6A 01            PUSH 0x1
 *  0043E1DB   8BCF             MOV ECX,EDI
 *  0043E1DD   FF90 4C010000    CALL DWORD PTR DS:[EAX+0x14C]
 *  0043E1E3   8B6C24 10        MOV EBP,DWORD PTR SS:[ESP+0x10]
 *  0043E1E7   8BCE             MOV ECX,ESI
 *  0043E1E9   C743 20 00000000 MOV DWORD PTR DS:[EBX+0x20],0x0
 *
 *  0043E1F0   E8 3B46FFFF      CALL .00432830
 *  0043E1F5   8987 A0030000    MOV DWORD PTR DS:[EDI+0x3A0],EAX
 *  0043E1FB   8D86 84C60000    LEA EAX,DWORD PTR DS:[ESI+0xC684]	; jichi: this is scenario
 *  0043E201   55               PUSH EBP
 *  0043E202   50               PUSH EAX
 *  0043E203   8BCF             MOV ECX,EDI
 *  0043E205   E8 765F0000      CALL .00444180
 *  0043E20A   8D9E 20C60000    LEA EBX,DWORD PTR DS:[ESI+0xC620]	; jichi: this is the chara name, such as KOT0
 *  0043E210   8D86 0FC60000    LEA EAX,DWORD PTR DS:[ESI+0xC60F]	; jichi: this is the name address
 *  0043E216   53               PUSH EBX
 *  0043E217   50               PUSH EAX
 *  0043E218   8BCF             MOV ECX,EDI
 *  0043E21A   894424 18        MOV DWORD PTR SS:[ESP+0x18],EAX
 *  0043E21E   E8 0D5F0000      CALL .00444130
 *
 *  0043E223   6A 01            PUSH 0x1
 *  0043E225   8BCF             MOV ECX,EDI
 *  0043E227   E8 04600000      CALL .00444230
 *  0043E22C   8A86 40BA0000    MOV AL,BYTE PTR DS:[ESI+0xBA40]
 *  0043E232   84C0             TEST AL,AL
 *  0043E234   0F84 DB000000    JE .0043E315
 *  0043E23A   8B86 18B50000    MOV EAX,DWORD PTR DS:[ESI+0xB518]
 *  0043E240   85C0             TEST EAX,EAX
 *  0043E242   0F84 CD000000    JE .0043E315
 *  0043E248   8B96 38B50000    MOV EDX,DWORD PTR DS:[ESI+0xB538]
 *  0043E24E   8DAE 38B50000    LEA EBP,DWORD PTR DS:[ESI+0xB538]
 *  0043E254   6A 00            PUSH 0x0
 *  0043E256   8BCD             MOV ECX,EBP
 *  0043E258   FF92 B4000000    CALL DWORD PTR DS:[EDX+0xB4]
 *  0043E25E   8B86 D8B10000    MOV EAX,DWORD PTR DS:[ESI+0xB1D8]
 *  0043E264   8D8E 70460000    LEA ECX,DWORD PTR DS:[ESI+0x4670]
 *  0043E26A   8D96 28670000    LEA EDX,DWORD PTR DS:[ESI+0x6728]
 *  0043E270   898E F8040000    MOV DWORD PTR DS:[ESI+0x4F8],ECX
 *  0043E276   894424 14        MOV DWORD PTR SS:[ESP+0x14],EAX
 *  0043E27A   89AE D8B10000    MOV DWORD PTR DS:[ESI+0xB1D8],EBP
 *  0043E280   C686 30B50000 01 MOV BYTE PTR DS:[ESI+0xB530],0x1
 *  0043E287   8996 FC040000    MOV DWORD PTR DS:[ESI+0x4FC],EDX
 *  0043E28D   8B87 AC030000    MOV EAX,DWORD PTR DS:[EDI+0x3AC]
 *  0043E293   6A 01            PUSH 0x1
 *  0043E295   8D4C24 1C        LEA ECX,DWORD PTR SS:[ESP+0x1C]
 *  0043E299   6A 01            PUSH 0x1
 *  0043E29B   51               PUSH ECX
 *  0043E29C   50               PUSH EAX
 *  0043E29D   8BCD             MOV ECX,EBP
 *  0043E29F   E8 DC570000      CALL .00443A80
 *  0043E2A4   8B5424 14        MOV EDX,DWORD PTR SS:[ESP+0x14]
 *  0043E2A8   8D8E 00050000    LEA ECX,DWORD PTR DS:[ESI+0x500]
 *  0043E2AE   8996 D8B10000    MOV DWORD PTR DS:[ESI+0xB1D8],EDX
 *  0043E2B4   8D96 B8250000    LEA EDX,DWORD PTR DS:[ESI+0x25B8]
 *  0043E2BA   85C0             TEST EAX,EAX
 *  0043E2BC   C686 30B50000 00 MOV BYTE PTR DS:[ESI+0xB530],0x0
 *  0043E2C3   898E F8040000    MOV DWORD PTR DS:[ESI+0x4F8],ECX
 *  0043E2C9   8996 FC040000    MOV DWORD PTR DS:[ESI+0x4FC],EDX
 *  0043E2CF   7E 44            JLE SHORT .0043E315
 *  0043E2D1   8A86 41BA0000    MOV AL,BYTE PTR DS:[ESI+0xBA41]
 *  0043E2D7   84C0             TEST AL,AL
 *  0043E2D9   74 0A            JE SHORT .0043E2E5
 *  0043E2DB   33C0             XOR EAX,EAX
 *  0043E2DD   8A86 42BA0000    MOV AL,BYTE PTR DS:[ESI+0xBA42]
 *  0043E2E3   EB 02            JMP SHORT .0043E2E7
 *  0043E2E5   33C0             XOR EAX,EAX
 *  0043E2E7   8B4C24 24        MOV ECX,DWORD PTR SS:[ESP+0x24]
 *  0043E2EB   8B6C24 1C        MOV EBP,DWORD PTR SS:[ESP+0x1C]
 *  0043E2EF   8B97 B0030000    MOV EDX,DWORD PTR DS:[EDI+0x3B0]
 *  0043E2F5   50               PUSH EAX
 *  0043E2F6   8B4424 14        MOV EAX,DWORD PTR SS:[ESP+0x14]
 *  0043E2FA   2BCD             SUB ECX,EBP
 *  0043E2FC   53               PUSH EBX
 *  0043E2FD   83C1 04          ADD ECX,0x4
 *  0043E300   50               PUSH EAX
 *  0043E301   8B87 AC030000    MOV EAX,DWORD PTR DS:[EDI+0x3AC]
 *  0043E307   51               PUSH ECX
 *  0043E308   52               PUSH EDX
 *  0043E309   50               PUSH EAX
 *  0043E30A   8D8E 10B50000    LEA ECX,DWORD PTR DS:[ESI+0xB510]
 *  0043E310   E8 7B270000      CALL .00440A90
 *  0043E315   803B 00          CMP BYTE PTR DS:[EBX],0x0
 *  0043E318   74 0C            JE SHORT .0043E326
 *  0043E31A   81C7 C9030000    ADD EDI,0x3C9
 *  0043E320   89BE 3CC60000    MOV DWORD PTR DS:[ESI+0xC63C],EDI
 *  0043E326   8B4C24 10        MOV ECX,DWORD PTR SS:[ESP+0x10]
 *  0043E32A   8D86 84C60000    LEA EAX,DWORD PTR DS:[ESI+0xC684]
 *  0043E330   8986 84D60000    MOV DWORD PTR DS:[ESI+0xD684],EAX
 *  0043E336   5F               POP EDI
 *  0043E337   5E               POP ESI
 *  0043E338   C603 00          MOV BYTE PTR DS:[EBX],0x0
 *  0043E33B   5D               POP EBP
 *  0043E33C   C601 00          MOV BYTE PTR DS:[ECX],0x0
 *  0043E33F   33C0             XOR EAX,EAX
 *  0043E341   5B               POP EBX
 *  0043E342   83C4 18          ADD ESP,0x18
 *  0043E345   C3               RETN
 *  0043E346   90               NOP
 *  0043E347   90               NOP
 *  0043E348   90               NOP
 *  0043E349   90               NOP
 *  0043E34A   90               NOP
 *  0043E34B   90               NOP
 */
bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario
{
  const uint8_t bytes[] = {
    0xe8, XX4,              // 0043e1f0   e8 3b46ffff      call .00432830
    0x89,0x87, XX4,         // 0043e1f5   8987 a0030000    mov dword ptr ds:[edi+0x3a0],eax
    0x8d,0x86, XX4,         // 0043e1fb   8d86 84c60000    lea eax,dword ptr ds:[esi+0xc684]	; jichi: this is scenario
                            // 0043e201   55               push ebp
                            // 0043e202   50               push eax
    XX4,                    // 0043e203   8bcf             mov ecx,edi
    0xe8, XX4,              // 0043e205   e8 765f0000      call .00444180
    0x8d,0x9e, XX4,         // 0043e20a   8d9e 20c60000    lea ebx,dword ptr ds:[esi+0xc620]	; jichi: this is the chara name, such as kot0
    0x8d,0x86, XX4,         // 0043e210   8d86 0fc60000    lea eax,dword ptr ds:[esi+0xc60f]	; jichi: this is the name address
    0x53,                   // 0043e216   53               push ebx
    0x50,                   // 0043e217   50               push eax
    0x8b,0xcf,              // 0043e218   8bcf             mov ecx,edi
    0x89,0x44,0x24, XX,     // 0043e21a   894424 18        mov dword ptr ss:[esp+0x18],eax
    0xe8 //, XX4            // 0043e21e   e8 0d5f0000      call .00444130
  };
  ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
  if (!addr)
    return false;

  Private::scenarioOffset_ = *(DWORD *)(addr + 2 + 0x0043e1fb - 0x0043e1f0);
  Private::nameOffset_ = *(DWORD *)(addr + 2 + 0x0043e210 - 0x0043e1f0);
  if ((Private::scenarioOffset_ >> 16) || // offset high bits are zero
      (Private::nameOffset_ >> 16))
    return false;

  addr = MemDbg::findEnclosingAlignedFunction(addr);
  if (!addr)
    return false;
  HookParam hp;
  hp.address=addr;
  hp.type=EMBED_ABLE|EMBED_DYNA_SJIS;
  hp.hook_before=Private::hookBefore;
  hp.hook_after=Private::hookafter; 
  hp.hook_font=F_GetGlyphOutlineA|F_GetTextExtentPoint32A;
  return NewHook(hp,"EmbedLucifen");
} 
} // namespace ScenarioHook

namespace ChoiceHook {
namespace Private {

  bool hookBefore(hook_stack*s,void* data, size_t* len1,uintptr_t*role)
  {
    static std::string data_;
    auto text = (LPCSTR)s->stack[0]; // arg1 is text
    if (!text || !*text)
      return text;
    *role=Engine::ChoiceRole;
    write_string_overwrite(data,len1,text);
    return true; 
  }
   void hookafter(hook_stack*s,void* data, size_t len1){
      
      auto newData =std::string((char*)data,len1); 
   strcpy((char*)s->stack[0], newData.c_str()); 
  }

} // namespace Private

/**
 *  Debugging method:
 *  - Hijack GetGlyphOutlineA
 *  - Backtrack stack to find text that used as argument
 *
 *  Sample game: プリズム・プリンセス
 *
 *  Text in arg1.
 *
 *  The function is only called by one caller.
 *  I suspect it is a virtual function, and hence caller is hooked.
 *
 *  0044235E   90               NOP
 *  0044235F   90               NOP
 *  00442360   83EC 08          SUB ESP,0x8
 *  00442363   53               PUSH EBX
 *  00442364   56               PUSH ESI
 *  00442365   8BF1             MOV ESI,ECX
 *  00442367   BB 01000000      MOV EBX,0x1
 *  0044236C   8A86 E2050000    MOV AL,BYTE PTR DS:[ESI+0x5E2]
 *  00442372   84C0             TEST AL,AL
 *  00442374   75 14            JNZ SHORT .0044238A
 *  00442376   889E BD040000    MOV BYTE PTR DS:[ESI+0x4BD],BL
 *  0044237C   E8 BFFAFFFF      CALL .00441E40
 *  00442381   85C0             TEST EAX,EAX
 *  00442383   0F94C0           SETE AL
 *  00442386   84C0             TEST AL,AL
 *  00442388   74 16            JE SHORT .004423A0
 *  0044238A   53               PUSH EBX
 *  0044238B   6A 00            PUSH 0x0
 *  0044238D   8BCE             MOV ECX,ESI
 *  0044238F   E8 2C80FFFF      CALL .0043A3C0
 *  00442394   85C0             TEST EAX,EAX
 *  00442396   74 16            JE SHORT .004423AE
 *  00442398   5E               POP ESI
 *  00442399   5B               POP EBX
 *  0044239A   83C4 08          ADD ESP,0x8
 *  0044239D   C2 0400          RETN 0x4
 *  004423A0   8B86 88040000    MOV EAX,DWORD PTR DS:[ESI+0x488]
 *  004423A6   8BCE             MOV ECX,ESI
 *  004423A8   50               PUSH EAX
 *  004423A9   E8 32120700      CALL .004B35E0
 *  004423AE   8B96 949E0000    MOV EDX,DWORD PTR DS:[ESI+0x9E94]
 *  004423B4   55               PUSH EBP
 *  004423B5   8DAE 949E0000    LEA EBP,DWORD PTR DS:[ESI+0x9E94]
 *  004423BB   57               PUSH EDI
 *  004423BC   8BCD             MOV ECX,EBP
 *  004423BE   C686 BD040000 00 MOV BYTE PTR DS:[ESI+0x4BD],0x0
 *  004423C5   FF92 80000000    CALL DWORD PTR DS:[EDX+0x80]
 *  004423CB   8B86 44040000    MOV EAX,DWORD PTR DS:[ESI+0x444]
 *  004423D1   85C0             TEST EAX,EAX
 *  004423D3   74 05            JE SHORT .004423DA
 *  004423D5   83C0 18          ADD EAX,0x18
 *  004423D8   EB 02            JMP SHORT .004423DC
 *  004423DA   33C0             XOR EAX,EAX
 *  004423DC   8B8E A0A00000    MOV ECX,DWORD PTR DS:[ESI+0xA0A0]
 *  004423E2   8B7C24 1C        MOV EDI,DWORD PTR SS:[ESP+0x1C]
 *  004423E6   8B55 00          MOV EDX,DWORD PTR SS:[EBP]
 *  004423E9   51               PUSH ECX
 *  004423EA   8B4F 4C          MOV ECX,DWORD PTR DS:[EDI+0x4C]
 *  004423ED   51               PUSH ECX
 *  004423EE   50               PUSH EAX
 *  004423EF   8BCD             MOV ECX,EBP
 *  004423F1   FF92 AC000000    CALL DWORD PTR DS:[EDX+0xAC]
 *  004423F7   B8 02000000      MOV EAX,0x2
 *  004423FC   8D4F 08          LEA ECX,DWORD PTR DS:[EDI+0x8]
 *  004423FF   8339 00          CMP DWORD PTR DS:[ECX],0x0
 *  00442402   74 0B            JE SHORT .0044240F
 *  00442404   83C0 02          ADD EAX,0x2
 *  00442407   83C1 08          ADD ECX,0x8
 *  0044240A   83F8 12          CMP EAX,0x12
 *  0044240D  ^7C F0            JL SHORT .004423FF
 *  0044240F   D1F8             SAR EAX,1
 *  00442411   48               DEC EAX
 *  00442412   8BF8             MOV EDI,EAX
 *  00442414   8A86 30A60000    MOV AL,BYTE PTR DS:[ESI+0xA630]
 *  0044241A   84C0             TEST AL,AL
 *  0044241C   897C24 14        MOV DWORD PTR SS:[ESP+0x14],EDI
 *  00442420   89BE 9CA00000    MOV DWORD PTR DS:[ESI+0xA09C],EDI
 *  00442426   0F84 B9000000    JE .004424E5
 *  0044242C   8B86 C0A00000    MOV EAX,DWORD PTR DS:[ESI+0xA0C0]
 *  00442432   85C0             TEST EAX,EAX
 *  00442434   0F84 AB000000    JE .004424E5
 *  0044243A   57               PUSH EDI
 *  0044243B   8D8E B8A00000    LEA ECX,DWORD PTR DS:[ESI+0xA0B8]
 *  00442441   885C24 17        MOV BYTE PTR SS:[ESP+0x17],BL
 *  00442445   E8 46270000      CALL .00444B90
 *  0044244A   33DB             XOR EBX,EBX
 *  0044244C   85FF             TEST EDI,EDI
 *  0044244E   7E 64            JLE SHORT .004424B4
 *  00442450   8B5424 1C        MOV EDX,DWORD PTR SS:[ESP+0x1C]
 *  00442454   8D7A 0C          LEA EDI,DWORD PTR DS:[EDX+0xC]
 *  00442457   8A941E B8040000  MOV DL,BYTE PTR DS:[ESI+EBX+0x4B8]
 *  0044245E   8B45 00          MOV EAX,DWORD PTR SS:[EBP]
 *  00442461   6A 00            PUSH 0x0
 *  00442463   6A 00            PUSH 0x0
 *  00442465   84D2             TEST DL,DL
 *  00442467   8B17             MOV EDX,DWORD PTR DS:[EDI]
 *  00442469   6A 00            PUSH 0x0
 *  0044246B   0F954424 28      SETNE BYTE PTR SS:[ESP+0x28]
 *  00442470   8B4C24 28        MOV ECX,DWORD PTR SS:[ESP+0x28]
 *  00442474   6A 00            PUSH 0x0
 *  00442476   6A FF            PUSH -0x1
 *  00442478   6A 00            PUSH 0x0
 *  0044247A   6A FF            PUSH -0x1
 *  0044247C   51               PUSH ECX
 *  0044247D   6A 00            PUSH 0x0
 *  0044247F   52               PUSH EDX
 *  00442480   8BCD             MOV ECX,EBP
 *  00442482   FF90 84000000    CALL DWORD PTR DS:[EAX+0x84]             ; .004BBD00	; jichi: text called here, text on the top
 *  00442488   8A4424 13        MOV AL,BYTE PTR SS:[ESP+0x13]
 *  0044248C   84C0             TEST AL,AL
 *  0044248E   74 18            JE SHORT .004424A8
 *  00442490   8A5424 1C        MOV DL,BYTE PTR SS:[ESP+0x1C]
 *  00442494   8B0F             MOV ECX,DWORD PTR DS:[EDI]
 *  00442496   84D2             TEST DL,DL
 *  00442498   0F94C0           SETE AL
 *  0044249B   50               PUSH EAX
 *  0044249C   51               PUSH ECX
 *  0044249D   8D8E B8A00000    LEA ECX,DWORD PTR DS:[ESI+0xA0B8]
 *  004424A3   E8 48280000      CALL .00444CF0
 *  004424A8   8B4424 14        MOV EAX,DWORD PTR SS:[ESP+0x14]
 *  004424AC   83C7 08          ADD EDI,0x8
 *  004424AF   43               INC EBX
 *  004424B0   3BD8             CMP EBX,EAX
 *  004424B2  ^7C A3            JL SHORT .00442457
 *  004424B4   8A4424 13        MOV AL,BYTE PTR SS:[ESP+0x13]
 *  004424B8   5F               POP EDI
 *  004424B9   84C0             TEST AL,AL
 *  004424BB   5D               POP EBP
 *  004424BC   74 12            JE SHORT .004424D0
 *  004424BE   8D96 34A60000    LEA EDX,DWORD PTR DS:[ESI+0xA634]
 *  004424C4   8D8E B8A00000    LEA ECX,DWORD PTR DS:[ESI+0xA0B8]
 *  004424CA   52               PUSH EDX
 *  004424CB   E8 B0280000      CALL .00444D80
 *  004424D0   33C0             XOR EAX,EAX
 *  004424D2   81C6 B8040000    ADD ESI,0x4B8
 *  004424D8   8906             MOV DWORD PTR DS:[ESI],EAX
 *  004424DA   8846 04          MOV BYTE PTR DS:[ESI+0x4],AL
 *  004424DD   5E               POP ESI
 *  004424DE   5B               POP EBX
 *  004424DF   83C4 08          ADD ESP,0x8
 *  004424E2   C2 0400          RETN 0x4
 *  004424E5   C64424 13 00     MOV BYTE PTR SS:[ESP+0x13],0x0
 *  004424EA  ^E9 5BFFFFFF      JMP .0044244A
 *  004424EF   90               NOP
 *  004424F0   8B4424 04        MOV EAX,DWORD PTR SS:[ESP+0x4]
 *  004424F4   8B40 04          MOV EAX,DWORD PTR DS:[EAX+0x4]
 *  004424F7   85C0             TEST EAX,EAX
 *  004424F9   7C 0D            JL SHORT .00442508
 *  004424FB   83F8 05          CMP EAX,0x5
 *  004424FE   7D 08            JGE SHORT .00442508
 *  00442500   C68408 B8040000 >MOV BYTE PTR DS:[EAX+ECX+0x4B8],0x1
 *  00442508   33C0             XOR EAX,EAX
 *  0044250A   C2 0400          RETN 0x4
 *  0044250D   90               NOP
 *  0044250E   90               NOP
 */
bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario
{
  const uint8_t bytes[] = {
    0xff,0x90, 0x84,0x00,0x00,0x00, // 00442482   ff90 84000000    call dword ptr ds:[eax+0x84]             ; .004bbd00	; jichi: text called here, text on the top
    0x8a,0x44,0x24, 0x13            // 00442488   8a4424 13        mov al,byte ptr ss:[esp+0x13]
  };
  ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
  if(addr==0)return false;
  HookParam hp;
  hp.address=addr;
  hp.type=EMBED_ABLE|EMBED_DYNA_SJIS;
  hp.hook_before=Private::hookBefore;
  hp.hook_after=Private::hookafter; 
  hp.hook_font=F_GetGlyphOutlineA|F_GetTextExtentPoint32A;
  return NewHook(hp,"lucifen_choice");
}
} // namespace ChoiceHook
 
  size_t  countZero(const char *s, size_t limit=1500)
{
  size_t count = 0;
  for (auto p = s; !*p && count < limit; p++, count++);
  return count == limit ? 0 : count;
}bool hookBefore(hook_stack*s,void* data, size_t* len1,uintptr_t*role)
  {
    auto text = (LPSTR)s->stack[1]; // arg1 is text
    if (!text || ::strlen(text) <= 2 )
      return false;
    *role=Engine::OtherRole;
    std::string oldData =text;
    strcpy((char*)data,oldData.c_str());*len1=oldData.size();
    return true; 
  }
  void hookafter(hook_stack*s,void* data, size_t len1){
     auto text = (LPSTR)s->stack[1]; // arg1 is text
     
    enum { role = Engine::OtherRole };std::string oldData = text ;
    auto split = s->stack[0]; 
       auto newData =std::string((char*)data,len1); 
    size_t capacity =  countZero(text + oldData.size());
    if (!capacity)
      return  ;
    capacity += oldData.size() - 1;
    if (newData.size() > capacity)
      newData = newData.substr(0,capacity);
   if (newData.size() < oldData.size())
     ::memset(text + newData.size(), 0, oldData.size() - newData.size());
    ::strcpy(text, newData.c_str()); 
    return  ;
  }
bool attach11(ULONG startAddress, ULONG stopAddress) // attach scenario
{
  //这个的对话都是一个个字的,但是名字是连续的。
  const uint8_t bytes[] = {
    0x83,0xec, 0x14,                // 00461ca0   83ec 14          sub esp,0x14
    0x33,0xd2,                      // 00461ca3   33d2             xor edx,edx
    0x55,                           // 00461ca5   55               push ebp
    0x56,                           // 00461ca6   56               push esi
    0x8b,0x74,0x24, 0x20,           // 00461ca7   8b7424 20        mov esi,dword ptr ss:[esp+0x20]
    0x8b,0xe9,                      // 00461cab   8be9             mov ebp,ecx
    0x3b,0xf2,                      // 00461cad   3bf2             cmp esi,edx
    0x0f,0x84, 0x55,0x02,0x00,0x00, // 00461caf   0f84 55020000    je .00461f0a
    0x39,0x55, 0x08,                // 00461cb5   3955 08          cmp dword ptr ss:[ebp+0x8],edx
    0x0f,0x84, 0x4c,0x02,0x00,0x00, // 00461cb8   0f84 4c020000    je .00461f0a
    0x8b,0x85, 0x74,0x20,0x00,0x00  // 00461cbe   8b85 74200000    mov eax,dword ptr ss:[ebp+0x2074]
  };
  ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
  if(addr==0)return false;
  HookParam hp;
  hp.address=addr;
  hp.offset=get_stack(1); 
  hp.type=EMBED_ABLE|EMBED_DYNA_SJIS; 
  hp.hook_after=hookafter; 
  hp.hook_before=hookBefore;
  hp.hook_font=F_GetGlyphOutlineA|F_GetTextExtentPoint32A;
  return NewHook(hp,"Embedlucifen2");
  
}
}
bool Lucifen::attach_function() {
    bool b1=ScenarioHook::attach(processStartAddress,processStopAddress)||  attach_navel(processStartAddress,processStopAddress);
    if(b1){
      ChoiceHook::attach(processStartAddress,processStopAddress);
      attach11(processStartAddress,processStopAddress);
    }
    
    bool succ=InsertLucifenHook();
    succ|=hook();
    return succ;
}