Author Topic: Xenogears fieldscript.  (Read 6121 times)

Akari

  • *
  • Posts: 766
    • View Profile
Xenogears fieldscript.
« on: 2006-07-31 13:41:59 »
I spent some times playing with xenogears field files again.
I managed to understand some new data.

If anyone still remember something - file six in field are scripts.
The first 0x80 bytes are unknown.
After it goes u32 number of entitys.
And after it are 2 bytes offsets to entity scripts entry points. Each entity record are 0x40 bytes long so there can be 32 scripts max.
The first script are called at the beginning of the map (constructor)
The second one are called repeatedly
The third one are the dialog script (called when you try to speak with entity)

Here some script that I already decode... not compleatly maybe =)

Code: [Select]
0x00         Return();

0x01         JumpTo(u16 address);
                 address   - address in global script offset

0x02         ConditionalJumpTo(u8 offset, u8 databank, u16 value, u8 condition, u16 address);
                 if condition is wrong then jump
                 condition - 0x40 - A == B
                           - 0x41 - A != B
                           - 0x46 - A &  B
                 address   - address in global script offset

0x0B         SpriteSet(u8 sprite_id, 80);

0x19         SpriteSetPosition(u16 x, u16 y, C0);

0x20         SpriteSetSolid(u8 type, 80);
                 type      - 0x01 - can go through
                           - 0x02 - ???
                           - 0x04 - ???
                           - 0x08 - can't move
                           - and different combination of above flags

0x26         Wait(u8 time, 80);
                 time      - the larger value - longer waiting

0x2C         SpritePlayAnimation(u8 animation_id);

0x36         VariableSetTrue(u8 offset, u8 databank);
                 set two bytes from offset to 01 00

0x37         VariableSetFalse(u8 offset, u8 databank);
                 set two bytes from offset to 00 00

0x4A         SpriteGoToPosition(u16 x, u16 y, C0);

0x69         SpriteSetDirection(u8 direction, 80);
                 direction - 0x00 - north
                           - 0x01 - north-east
                           - 0x02 - east
                           - 0x03 - south-east
                           - 0x04 - south
                           - 0x05 - south-west
                           - 0x06 - west
                           - 0x07 - north-west
                           - and so on...

0x6B         SpriteRotateClockwise(u8 rotation, 80);
                 rotation  - number of sprite rotation to skip (clockwise)
                           - 0x00 - stay as we are
                           - 0x01 - rotate one position clockwise

0x6C         SpriteRotateAntiClockwise(u8 rotation, 80);
                 rotation  - number of sprite rotation to skip (anti-clockwise)
                           - 0x00 - stay as we are
                           - 0x01 - rotate one position anti-clockwise

0x6F         SpriteRotateToEntity(u8 entity_id);

0x98         MapLoad(u16 map_id, u8 location, 80);

0xA8         VariableRandom(u8 offset, u8 databank, u8 max_value, 80);
                 set two bytes from offset to random value from "00 00" to "max_value 00"

0xB3         FadeOut(u8 time, 80);
                 time      - larger the value - longer the fade

0xB4         FadeIn(u8 time, 80);
                 time      - larger the value - longer the fade

0xB5         CameraSetDirection(u8 direction, 80);
                 direction - 0x00 - north
                           - 0x01 - north-east
                           - 0x02 - east
                           - 0x03 - south-east
                           - 0x04 - south
                           - 0x05 - south-west
                           - 0x06 - west
                           - 0x07 - north-west
                           - and so on...

0xC7         CameraRotate(u8 time, 80);
                 don't know difference with CameraRotate2();
                 time      - larger the value - longer the rotate

0xC8         CameraRotate2(u8 time, 80);
                 don't know difference with CameraRotate();
                 time      - larger the value - longer the rotate

0xD2         DialogShow(u8 dialog_id, u16 flags);
                 flags meaning are dont known

And example script. The main room in Chief Lee house (where the first conversation with Dan is). Entity is Maid that walking in far corner of the room.

Code: [Select]
// 0x04C5
entity[0F].script[00]()
{
    SpriteSet(03, 80);
    Return();
}



// 0x04C9
entity[0F].script[01]()
{
    VariableRandom(0E, 04, 03, 80);
    ConditionalJumpTo(0E, 04, 00 00, 40, E5 04); (#1)
    SpriteGoToPosition(86 FF, B9 01, C0);
    SpriteSetDirection(00, 80);
    Wait(28, 80);
    JumpTo(36 05); (#4)
#1  ConditionalJumpTo(0E, 04, 01 00, 40, FC 04); (#2)
    SpriteGoToPosition(20 00, B9 01, C0);
    SpriteSetDirection(00, 80);
    Wait(28, 80);
    JumpTo(36 05); (#4)
#2  ConditionalJumpTo(0E, 04, 02 00, 40, 13 05); (#3)
    SpriteGoToPosition(4D FF, 56 01, C0);
    SpriteSetDirection(06, 80);
    Wait(28, 80);
    JumpTo(36 05); (#4)
#3  ConditionalJumpTo(0E, 04, 03 00, 40, 36 05); (#4)
    SpriteSetDirection(01, 80);
    Wait(05, 80);
    SpriteSetDirection(00, 80);
    Wait(05, 80);
    SpriteSetDirection(07, 80);
    Wait(05, 80);
    SpriteSetDirection(00, 80);
    Wait(1E, 80);
    JumpTo(36 05); (#4)
#4  04
}



// 0x0537
entity[0F].script[02]()
{
    ConditionalJumpTo(02, 04, 00 00, 40, 42 05); (#1)
    JumpTo(43 05); (#2)
#1  Return();
#2  SpriteRotateToEntity(01);
    DialogShow(22, 00 00);
    9C
    5D025E
    DialogShow(23, 00 00);
    9C
    2CFF
}



// 0x0554
entity[0F].script[03]()
{
    Return();
}



// 0x0555
entity[0F].script[04]()
{
    F4005A
    92
}



// 0x0559

And one more. Chief Lee itself

Code: [Select]
Lee

// 0x03AA
entity[0C].script[00]()
{
    SpriteSet(04, 80);
    SpriteSetSolid(08, 80);
    SpriteSetDirection(00, 80);
    FE0D0F80
    Return();
}



// 0x03B8
entity[0C].script[01]()
{
    Return();
}



// 0x03B9
entity[0C].script[02]()
{
    VariableSetTrue(02, 04);
    SpriteRotateToEntity(01);
    ConditionalJumpTo(0C, 04, 00 00, 40, 07 04); (#1)
    DialogShow(1A, 00 00);
    9C
    SpriteRotateClockwise(01, 80);
    Wait(05, 80);
    SpriteRotateAntiClockwise(01, 80);
    Wait(0A, 80);
    DialogShow(1B, 00 00);
    9C
    SpritePlayAnimation(00);
    SpriteRotateClockwise(01, 80);
    Wait(01, 80);
    SpriteRotateClockwise(01, 80);
    FE0DFC80
    DialogShow(1C, 00 00);
    9C
    FE0D0F80
    Wait(0A, 80);
    SpriteRotateToEntity(01);
    Wait(0A, 80);
    DialogShow(1D, 00 00);
    9C
    VariableSetTrue(0C, 04)
    JumpTo(0C 04); (#2)
#1  DialogShow(1E, 00 00);
    9C
#2  SpritePlayAnimation(FF);
    370204
}



// 0x0411
entity[0C].script[03]()
{
    Return();
}



// 0x0412
entity[0C].script[04]()
{
    Wait(14, 80);
    A40C00DA00
}



// 0x041A
entity[0C].script[05]()
{
    A419008F00
}



// 0x041F
entity[0C].script[06]()
{
    ConditionalJumpTo(08, 00, 06 00, 40, 2F 04); (#1)
    CameraSetDirection(02, 80);
    3C80
    JumpTo(54 04); (#4)
#1  ConditionalJumpTo(08, 00, 07 00, 40, 3F 04); (#2)
    CameraSetDirection(02,80);
    2880
    JumpTo(54 04); (#4)
#2  ConditionalJumpTo(08, 00, 05 00, 40, 4F 04); (#3)
    CameraSetDirection(02, 80);
    2880
    JumpTo(54 04); (#4)
#3  CameraSetDirection(02, 80);
    1E80
#4  Return();
}



// 0x0455
entity[0C].script[06]()
{
    F4005A
    SpriteSetDirection(00, 80);
    92
}



// 0x045C

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Xenogears fieldscript.
« Reply #1 on: 2006-08-02 16:39:43 »
Akari how similiar are the opcodes to FF7's? It looks as if it uses a different encoding but similiar opcodes.  Obviously they needed different opcodes.
32 is identical to FF7's count and it sounds like they have a periodic update function.  Is there empty routines for unused slots like in FF7?
I wonder if it should use the same scripting code layout as for FF7. Hmmm.

Anyhow great work. As ussual ;)
Cyb

Akari

  • *
  • Posts: 766
    • View Profile
Re: Xenogears fieldscript.
« Reply #2 on: 2006-08-03 15:34:33 »
Akari how similiar are the opcodes to FF7's? It looks as if it uses a different encoding but similiar opcodes.  Obviously they needed different opcodes.

The base opcode idea are the same. There are also opcodes for math operations, script calling, different type of jumps, dialog windows, background management, menu calling. character management. Although they are very game specific, all of them (exept return) have different format and different argument layout. Ow.. I forgot that there are camera management opcodes =)
And... there are more than 256 opcodes =)

Quote
32 is identical to FF7's count and it sounds like they have a periodic update function.  Is there empty routines for unused slots like in FF7?
I wonder if it should use the same scripting code layout as for FF7. Hmmm.

Khmmm.. i dont remember  empty routines for unused slots... what is it?

The only difference I met is the update script (script that are called repeatedly) are exist as independant script, not as the part of script 0.

Quote
Anyhow great work. As ussual ;)

Thanks  :-D

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Xenogears fieldscript.
« Reply #3 on: 2006-08-04 06:48:49 »
The base opcode idea are the same. There are also opcodes for math operations, script calling, different type of jumps, dialog windows, background management, menu calling. character management. Although they are very game specific, all of them (exept return) have different format and different argument layout. Ow.. I forgot that there are camera management opcodes =)
And... there are more than 256 opcodes =)
Multibyte encoding? Interesting.  I suspect that is what FF8's script system does too! LOL.  Basically it's a completely different encoding system.  Might be a different script engine all together as well.  The only thing the same is RET! ;)
Khmmm.. i dont remember  empty routines for unused slots... what is it?
In FF7 if a slot (IE script location) doesn't have any code it contains a RET and the script table has an offset to the RET for the routine.  It appears that the engine for Xenogears doesn't do this that is all I was noticing.  In all the Xenogears script system is more efficient. :D
The only difference I met is the update script (script that are called repeatedly) are exist as independant script, not as the part of script 0.
That's very interesting, I think it's a much more elegant and less messy way of doing it.

Thanks  :-D
Well I've noticed I don't give out compliments easily, so I guess I can honestly say it's likely true. ;)

Anyhow I am working on a GTK/Linux version of my system for reviewing Square data.  I may borrow Q-gears ISO file system code to do it as well.  At least if I use GTK/Eclipse under Linux I'll have something that works and I won't need to worry about loosing the silly source code all the time.

Cyb

Akari

  • *
  • Posts: 766
    • View Profile
Re: Xenogears fieldscript.
« Reply #4 on: 2006-08-04 08:07:32 »
The base opcode idea are the same. There are also opcodes for math operations, script calling, different type of jumps, dialog windows, background management, menu calling. character management. Although they are very game specific, all of them (exept return) have different format and different argument layout. Ow.. I forgot that there are camera management opcodes =)
And... there are more than 256 opcodes =)
Multibyte encoding? Interesting.  I suspect that is what FF8's script system does too! LOL.  Basically it's a completely different encoding system.  Might be a different script engine all together as well.  The only thing the same is RET! ;)

It works the same way. Just you can't count opcode 0xFE instead of this you can found a lot of opcodes that start from 0xFE00, 0xFE01, 0xFE02 and so on. So if system met 0xFE it's just read one more byte.

Oh and I found Request opcodes =)
0x08         EntityCallScriptSW(u8 entity, u4 priority, u4 script);
                 waits till script starts working and then continue

0x09         EntityCallScriptEW(u8 entity, u4 priority, u4 script);
                 waits till script finishes working and then continue

I still don't know what 0x80 in the end of many opcodes means =(

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Xenogears fieldscript.
« Reply #5 on: 2006-08-04 14:22:51 »
Multibyte encoding? Interesting.  I suspect that is what FF8's script system does too! LOL.  Basically it's a completely different encoding system.  Might be a different script engine all together as well.  The only thing the same is RET! ;)
It works the same way. Just you can't count opcode 0xFE instead of this you can found a lot of opcodes that start from 0xFE00, 0xFE01, 0xFE02 and so on. So if system met 0xFE it's just read one more byte.
So 0xFE is Xenogears SPECIAL (0x0F) opcode basically.

Oh and I found Request opcodes =)
0x08         EntityCallScriptSW(u8 entity, u4 priority, u4 script);
                 waits till script starts working and then continue

0x09         EntityCallScriptEW(u8 entity, u4 priority, u4 script);
                 waits till script finishes working and then continue

I still don't know what 0x80 in the end of many opcodes means =(
Quote
There are 32 scripts Akari what's the chance the encoding is 3:5 instead of 4:4 on the second byte like FF7's engine?

More stuff for the Wiki in any case :D

I need to get more time! Have any spare?

Cyb

Micky

  • *
  • Posts: 300
    • View Profile
Re: Xenogears fieldscript.
« Reply #6 on: 2006-08-04 19:51:51 »
Awesome.
So, is this going to be supported by Q-Gears, or are you going to make X-Gears ? :D

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
Re: Xenogears fieldscript.
« Reply #7 on: 2006-08-05 01:30:02 »
I have to object...

You can't call it X-gears as you are not allowed to have a name cooler than mine....

 :x  :|

Akari

  • *
  • Posts: 766
    • View Profile
Re: Xenogears fieldscript.
« Reply #8 on: 2006-08-05 15:48:04 »
I have to object...

You can't call it X-gears as you are not allowed to have a name cooler than mine....

 :x  :|

I think Q-Gears must handle different square games that share similar engine. FFVII, FFVIII, FFIX, Xenogears, Chrono Cross, Parasite Eve and maybe even futher (FFX?).

I still can't deside the better way to do it.

Cyberman

  • *
  • Posts: 1572
    • View Profile
Re: Xenogears fieldscript.
« Reply #9 on: 2006-08-05 16:56:59 »
I think Q-Gears must handle different square games that share similar engine. FFVII, FFVIII, FFIX, Xenogears, Chrono Cross, Parasite Eve and maybe even futher (FFX?).

I still can't deside the better way to do it.
FFX I believe was started in 1998 and the engine is likely completely different.  Although it might not be.  There weren't a lot of entities in each level.  The big difference is likely the content of the game not the script engine. :D
Vagrant story had a similiar engine design as well.  Although not as well known and didn't have a sequel, it was quite a ground breaking game.  Things to note about it is that many of it's features are similiar to FF10 in some ways.  So I'm sure the ideas migrated between the teams.
I digress Q-gears should be modular enough to accept multiple games. Obviously FF7 will be first ;) (or halkun will go on the war path).  Erstwhile during the restructuring of source file heirachy I'm going to test my ISO code and see what I can read.

The rest in Q-gears forum ;)

Cyb