Qhimm.com Forums
Miscellaneous Forums => Scripting and Reverse Engineering => Topic started by: Akari 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 =)
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.
// 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
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
-
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 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 =)
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.
Anyhow great work. As ussual ;)
Thanks :-D
-
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
-
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 =(
-
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 =(
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
-
Awesome.
So, is this going to be supported by Q-Gears, or are you going to make X-Gears ? :D
-
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 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.
-
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