int rjc(int size, UCHAR *p0, int mode)
/* mode: 0:decode, 1:encode */
{
UCHAR *p = p0, *p1 = p0 + size, *pp = p0 - 4;
int ofs0 = 0, ofs = 0, ofs1 = size;
int i, j, k, m = 0;
while (p < p1) {
if (0xe8 <= *p && *p <= 0xe9 && &p[4] < p1) { /* e8 (call32), e9 (jmp32) */
r32:
p++;
if (p - pp < 4)
continue;
i = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
k = i;
j = (p - p0) + ofs + 4; /* 相対アドレス基点 */
pp = p;
if (i == 0 || i == 0x80808080)
i ^= 0x80808080;
if (mode) { /* encode */
if (ofs0 - j <= i && i < ofs1 - j)
i += j;
else if (ofs1 - j <= i && i < ofs1)
i -= ofs1 - ofs0;
} else { /* decode */
if (ofs0 <= i && i < ofs1)
i -= j;
else if (ofs0 - j <= i && i < ofs0)
i += ofs1 - ofs0;
}
if (i == 0 || i == 0x80808080)
i ^= 0x80808080;
if (i != k) {
p[0] = i & 0xff;
p[1] = (i >> 8) & 0xff;
p[2] = (i >> 16) & 0xff;
p[3] = (i >> 24) & 0xff;
p += 4;
m++;
}
continue;
}
p++;
if (p[-1] == 0x0f && &p[4] < p1 && (p[0] & 0xf0) == 0x80) /* 0f 8x (jcc32) */
goto r32;
}
return m;
}