插件下载:
HarmoFavo
1 2 3 4 5 6 7
| v0.2[2014.2.19] [+]全自动配置 v0.11[2014.2.19] [+]支持Wiz Anniversary、funta支持不能……那玩意章节表比较奇葩、 [+]CG Patch v0.1 [2014.2.3] 第一个版本
|
本插件理论上支持所有使用Favorite社游戏引擎的游戏、并且目前已有的3个汉化版全部支持、现在已经支持全自动和谐……您只需要将本插件释放到游戏目录并用AlphaROMdiE装载游戏即可。
使用方法:【请在使用前认真阅读!
首先确保您的游戏目录是这样的、HarmoFavo下载下去以后直接释放到游戏目录即可
上个图证明可以支持光鸟鸟、色鸟鸟也可以支持、方法看评论一楼的回复
和谐后的光鸟鸟、其他的图就不上了……那个加奈和澪的3P因为是男猪开脑洞梦到的……所以那个没辙╮( ̄▽ ̄”)╭ 顾及18R的小盆友要玩的时候要小心这个坑。
【这里为老版本的说明、不必阅读】然后打开plugin目录、创建一个文本文档命名为config、然后里面的内容是需要解析的游戏的hcb文件。【为了兼容各种汉化补丁所以没有搞成自动的、搞成自动的兼容性会降低的。然后把那个文件从游戏目录复制到plugin目录下、比如我要让星空的记忆FD汉化版和谐一下,就复制汉化后的脚本执行体hoshimemo_ehchn.bch到plugin目录然后再填写config的内容即可。如下图
然后回到游戏目录、启动AlphaROMdiE、勾选禁止转码、把游戏可执行文件拖到上面、比如汉化版是Hoshimemo_EHchn.exe、然后会生成一个快捷方式、以后从这里点进去就是和谐版的游戏啦~
和谐效果如下图
被屏蔽掉的肯定就是H图啦~
有一个误伤的没办法、后来确认了下那张CG的确是出现在某H情节里……
啧啧啧、看看这有多少H
ETC的内容还是可以全部看到的_(:з」∠)_这里一般不会有H的
吐槽时间:
_(:з」∠)_这两天戳了下Favorite的引擎、感谢AmaranthF对Favorite社游戏引擎的vm拆解……
hcb可执行体主要分成几个区域
1 2 3 4 5 6 7 8 9 10 11
| ——————— public functions ——————— dispatcher ——————— para jumper[optional] ——————— para code ——————— H memo code ———————
|
目前的做法比较简单粗暴、就是计算一下H memo code起始的地方、如果有call到这里的话直接给ret回去
插件关键代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| vector<DWORD> ChcbVM::GetNCallSequence(DWORD & offset) { return GetLastNCallSequenceCond(offset,0x01); }
vector<DWORD> ChcbVM::GetLastNCallSequenceCond(DWORD & offset, BYTE bOP) { vector<DWORD> retVal; DWORD ori = bin.seek(0,FILE_CURRENT); bin.seek(offset,FILE_BEGIN); WORD tmp1; BYTE tmp0; do { bin.read(&tmp0,1); offset++; } while (tmp0!=0x01); bin.read(&tmp1,2); offset+=2; for (BYTE op;;) { op=bin.readb(); if (op == 0x2) { DWORD native = bin.readdw(); retVal.push_back(native); offset+=5; } else if (op==0x1) { break; } else if (op==bOP) { retVal.clear(); offset+=vmlde(op); } else { offset+=vmlde(op); } }
bin.seek(ori,FILE_BEGIN);
return retVal; }
int comp(const void* a,const void* b) { return *(PDWORD)a>*(PDWORD)b; }
vector<DWORD> ChcbVM::GetNCallList(DWORD & offset) { auto && res = GetNCallSequence(offset);
sort(res.begin(),res.end()); vector<DWORD> retVal; for (size_t idx = 0;idx<res.size();++idx) { if (*(retVal.end()-1)!=res[idx]) { retVal.push_back(res[idx]); } } return retVal; }
DWORD ChcbVM::AnalysisPara(void) { auto && res = GetLastNCallSequenceCond(hdr.EntryPoint,0x7);
DWORD offsetParaDispacher = 0; if (res.size()) { int idx = 1; search0: DWORD offset = res[idx]; auto && res2 = GetNCallSequence(offset); if (res2.size()<=2) { offsetParaDispacher = *(res2.end() - 1); } else { ++idx; goto search0; } } auto && ParaList = GetNCallList(offsetParaDispacher); return GetNextFuncOffset(*(ParaList.end() - 1)); }
typedef DWORD (__fastcall __pfnvCall)(void *unk1,DWORD unk0);
DWORD __fastcall vCall( void *unk1, DWORD unk0, DWORD RetAddr, __pfnvCall pfnvCall) { PDWORD pvIP = PDWORD((char *)unk1+offsetvIP); if (*pvIP>offsetLast) { *pvIP = offsetLast; return offsetLast; } return pfnvCall(unk1,unk0); }
|