Author Topic: World map event scripting  (Read 5363 times)

luksy

  • *
  • Posts: 375
    • View Profile
World map event scripting
« 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];
};
« Last Edit: 2012-06-27 07:29:16 by luksy »


luksy

  • *
  • Posts: 375
    • View Profile
Re: World map event scripting
« Reply #2 on: 2012-06-27 07:20:49 »
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.

luksy

  • *
  • Posts: 375
    • View Profile
Re: World map event scripting
« Reply #3 on: 2012-06-28 04:54:19 »
opcode 0x32d:

Code: [Select]
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;
}

luksy

  • *
  • Posts: 375
    • View Profile
Re: World map event scripting
« Reply #4 on: 2012-06-29 07:15:00 »
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.

Code: [Select]
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;
}
}
}
« Last Edit: 2012-06-29 07:19:10 by luksy »