插件下载:
HarmoFavo
| 12
 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可执行体主要分成几个区域
| 12
 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回去
插件关键代码
| 12
 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);
 }
 
 
 
 |