Qhimm.com Forums
Miscellaneous Forums => Scripting and Reverse Engineering => Topic started by: luksy on 2012-06-27 04:09:12
-
I've been poking around in the world map events, has anyone else had a look at the opcodes?
So far I have:
-----------------------------------
0x17
!(bool) stack top (resulting value pushed as if 0x110 was used)
-----------------------------------
0x100
Reset stack pointer to base (0xE3A7F0)
-----------------------------------
0x110
Push value to stack as word
-----------------------------------
0x114
Push value to stack as single bit from memory starting at offset *0xE3A7E0:
addr bit
|0000000000000|000|
-----------------------------------
0x201
if (!pop) jump to value as offset
-----------------------------------
0x203
End script
-----------------------------------
0x307
0xDE6B5C = stack top // Enable / disable controls
0xDFC4A8 = 3
-----------------------------------
0x32b // No idea
e3a890 = stack top
-----------------------------------
0x321 // Again no idea
*0xE2BB94 (ptr to 1 of 16 structs) = 0xE28CE0 + arg1 * 0x24
val1 = *(*E2BB94 + 8) - *(*E39AD8 + C + 8)
val2 = **E2BB94 - *(*E39AD8 + C)
*(*0xE39AD8 + 4C) = *(*0xE39AD8 + 40) = *(*0xE39AD8 + 3C) =
(((val1 << 8) / val2) *2) + 0xE37120
*0xE39AD8 + 3E = 0
-----------------------------------
0x324
Creates window using the top 4 values on stack, from bottom to top values are x, y, width, height
-----------------------------------
0x325
Places text using index on top of stack, text is read from mes.
-----------------------------------
0x326
Displays a question and saves user input (presumably to address on top of stack, haven't looked yet)
-----------------------------------
Stack base is always 0xE3A7F0, top of stack is stored at 0xE39ADC.
0x765E09 is a table of function pointers for 3xx opcodes.
0xE3A810 is a pointer to the current script op
The *.ev files have the following structure:
struct {
struct {
uint16_t id; // No idea yet
uint16_t offset;
} Header[0x100];
uint16_t data[0x3600];
};
-
I reverse it a little.
Script are here http://q-gears.hg.sourceforge.net/hgweb/q-gears/q-gears/file/5af809890403/reversing/ffvii/ffvii_wm/scripts/script_wm00.lua
It's not even half complete )
Reversed info here http://q-gears.hg.sourceforge.net/hgweb/q-gears/q-gears/file/5af809890403/reversing/ffvii/ffvii_wm/scripts
-
Cool, I actually had a look at the qGears source before, wonder why I didn't see that. Anyway I'm hoping to get the others done as well, maybe you'll find it useful too.
-
opcode 0x32d:
func 0x768E3D(int i)
{
int* j = *(i * 30 + 0x0CFF5E4) - 1;
if (*j > 12)
return 1;
switch(*j) {
case 0:
return 0;
case 1: case 3: case 5: case 7: case 10: case 12:
*j = 7;
return 1;
case 2: case 4: case 6: case 8: case 9: case 11:
return 1;
}
}
func 0x75EF13()
{
if (*0x0CFF5E4 && *0x0CFF5E4 != 7)
0x768E3D(0);
return !*0x0CFF5E4;
}
func 0x32d() // 0x765B86
{
if (!*0xE3A7DC) {
uint16_t i = 0x75EF13();
*(*0xE39AD8 + 46) -= i
return i;
}
return 0;
}
-
This should be all the 0x1xx ops:
0x110 - Push value
0x114 - Push bit from memory @*0x0E3A7E0 + top 13 bits of value, which bit is bottom 3.
0x118 - Get byte from memory @*0x0E3A7E0 + value
0x11C - Get word from memory @*0x0E3A7E0 + value
0x113 / 0x117 / 0x11B Value between 0 and 20 results in an extended opcode that pushes information from memory, see code.
func 0x753B73() {
for (int i = 0; i < 0x20; ++i)
*((uint8_t*)0xE2B550 + i) ^= *((char*)0xE2B739 + i);
for (int i = 20; i < 0x209; ++i)
*((uint8_t*)0xE2B550 + i) ^= *((char*)0xE2B530 + i);
}
func popStack() // 0x76488C
{
*pstack_top -= 8;
if ((push_op & 3) < 3) {
switch(push_op - 0x110) {
case 0:
return value;
case 4:
return (*(*0x0E3A7E0 + (value >> 3)) >> (value & 7)) & 1;
case 8:
return *(uint8_t*)(*0x0E3A7E0 + value);
case 0xC:
return *(uint16_t*)(*0x0E3A7E0 + value);
default:
return 0;
}
} else {
switch (value) {
case 0:
return *(*0xE39AD8 + 0xC) >> 0xD;
case 1:
return *(*0xE39AD8 + 0x14) >> 0xD;
case 2:
return *(*0xE39AD8 + 0xC) & 0x1FFF;
case 3:
return *(*0xE39AD8 + 0x14) & 0x1FFF;
case 4:
return (*(uint16_t*)(*0xE39AD8 + 0x40) >> 4) & 0xFF;
case 5:
return *0xE3A884;
case 6:
return *0xE3A894;
case 7:
return ((*(uint16_t*)0xE3A898 << 2) & 0xC) | (*0xDFC4B4 & 3);
case 8:
if (*0xE3A7D0)
return *(uint8_t*)(*0xE3A7D0 + 0x50);
return 0;
case 9:
return *(uint8_t*)0xDC0CD8;
case 0xA:
return !(*(uint16_t*)0xDB958A & 8);
case 0xB:
return *0xE2AB38;
case 0xC:
if (!*(uint16_t*)0xCFF5E4)
return -1;
return *(uint16_t*)0xE36104;
case 0xD:
return (*(uint16_t*)(*0xE39AD8 + 4A) >> 5) & 7;
case 0xE:
if (*(uint8_t*)0xDC09E5 == 2
|| *(uint8_t*)0xDC09E6 == 2
|| *(uint8_t*)0xDC09E7 == 2)
return 1;
if (*(uint8_t*)0xDC09E5 == 8
|| *(uint8_t*)0xDC09E6 == 8
|| *(uint8_t*)0xDC09E7 == 8)
return 2;
return 0;
case 0xF:
return *(uint8_t*)(*0xE39AD8 + 0x50);
case 0x10:
if ((*0xE2A138 += 1) >= 0x209) {
0x753B73();
*0xE2A138 = 0;
}
return *(uint8_t*)(*0xE2A138 + 0xE2B550);
case 0x11:
return *0xE39BA8;
case 0x12:
return *0xE39BAC;
case 0x13:
return *0xE39BA0;
case 0x14:
return *0xE39BA4;
default:
return 0;
}
}
}