Battle script (SCENE.BIN) + more

  • Thread starter Thread starter Cyberman
  • Start date Start date
Status
Not open for further replies.
I checked the uncompressed sizes, and ALL of them give me 7808 bytes, without exception. I made a basic "checksum" calculation for the blocks, and most of them give me different values, meaning there is different data, xcept for a few files that are empty (the ones that compress to only 11 words).
From that I deduce your decompression method doesn't work as it should.
That would be my conclusion too. Dang what a pain. It works perfect for everything else I've used it for though. When is a bug a feature? :D  I must be missing something specific in the decompression algorythm or I might be starting at the wrong location (the latter might be more likely).

EDIT: I have been trying to figure out how to "get" the script length, but I'm starting to think there isn't any length marker and the scripts just exit when they are done executing...
Script Length? No length marker that I am aware of I believe since the record size is fixed to 7808 bytes that means that you check if there are any scripts.  Then after that you perform much the same computation as you did to find the compressed file lengths (between scripts) the final one can be done using the end of the record. If you have one script though it means from the offset to the end of record is the AI.  There are a few battles that are like that.  Look at the ProudClod battle that might help.

Cyb
 
Script Length? No length marker that I am aware of I believe since the record size is fixed to 7808 bytes that means that you check if there are any scripts.  Then after that you perform much the same computation as you did to find the compressed file lengths (between scripts) the final one can be done using the end of the record. If you have one script though it means from the offset to the end of record is the AI.  There are a few battles that are like that.  Look at the ProudClod battle that might help.

Cyb
Ok done I had some troubles to figure out WHERE did the offsets start to count from: the first byte of the ai is the first byte of the offsets, so offset=6 is the first byte of actual data!

After that, each AI has a 16-entry script table with the offset counting from the start of the AI, so script_offset=0 would be the first byte of the table.

I have noticed all/most (haven't read all of them) end with a 0x73 byte, so I'm assuming opcode73=RET
Based on that assumption ("all scripts will end with a 0x73") I will also assume all the 0xFF bytes at the end are padding, and I will cut them (else the dump grows to 7mb).

EDIT: I did that, checked the last byte of all the scripts and yes, all of them, without exception, have a 0x73 as the last opcode.

EDIT2: As it's way too big to paste in a code block, I uploaded the output of my program to sendspace in case anyone wants to look at it.
 
Last edited:
What are you using to decompress each file in SCENE.BIN? I'm using much the same algorythm that's used in Q-gears. Ditto with you?

Cyb
 
I copied the code from qgears, and changed it to "fit" in my program, so basically I changed the parameters and return value, so I pass it a pointer and get the pointer to the uncompressed data as return value, and the size in a int pointer.
 
Ok well I used the code from Q-gears, the output and results are identical to my code.  Dare I ask are you doing something different? Somehow?
my first set of codes from the first file are (undecoded)
Code: [Select]
Code:
1F8B08000000000000000203ED96
 
yes that's the z "header"... I give the extractor from there to the end...

Interesting stuff I found at block 0, file 2:
Code: [Select]
Code:
Script at block 0, file 2, enemy 0, section 2:0000h: 81 60 08 34 0004h: 60 00 <-- there is another 60 xx pair below so maybe this one is a single instruction too... (if 71 is "jump if flag", this could be comparing?)0006h: 71 27 00 <-- 71 0x0027 == probably 71 is some "jump if (flag set?) to address 27h"0009h: 93 "monster" b2 "Not a probrem" b3 ff <-- 93 looks like a "show dialog" opcode 0021h: 72 62 00 <-- another jump, with diff condition code?0024h: 72 2c 000027h: 60 01 <-- I wonder...0029h: 71 46 00002ch: 93 "monster" b2 "I'm sorry" b3 ff 0040h: 72 62 00 0043h: 72 46 00 <-- given the next instruction is already at 46h, this looks like a "nop"...0046h: 93 "monster" b2 "That's too bad" b3 ff005fh: 72 62 00 0062h: 91 <-- I wonder too0063h: 73 20 00 <-- this 0x0020 points "nicely" to the 11 10 ... at the 0084h line, so it could mean 73 is a "jump offset"0066h: ff ff ff ff 006ah: 2b 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 0084h: 11 10 20 01 10 20 60 01 30 90 73008fh: 11 18 20 01 18 20 60 01 30 90 02 60 20 60 08 87 40 70 29 00 01 18 20 60 01 40 70 29 00 12 70 20 02 80 20 90 60 20 60 23 92 73
I will continue to look at it tomorrow, right now it's already 5am and I should be in bed. Cya.
 
Last edited:
dumb question, but why aren't you guys using terrence's monster AI dump as a template?
 
yes that's the z "header"... I give the extractor from there to the end...

Interesting stuff I found at block 0, file 2:
Code: [Select]
Code:
Script at block 0, file 2, enemy 0, section 2:0000h: 81 60 08 34 0004h: 60 00 <-- there is another 60 xx pair below so maybe this one is a single instruction too... (if 71 is "jump if flag", this could be comparing?)0006h: 71 27 00 <-- 71 0x0027 == probably 71 is some "jump if (flag set?) to address 27h"0009h: 93 "monster" b2 "Not a probrem" b3 ff <-- 93 looks like a "show dialog" opcode 0021h: 72 62 00 <-- another jump, with diff condition code?0024h: 72 2c 000027h: 60 01 <-- I wonder...0029h: 71 46 00002ch: 93 "monster" b2 "I'm sorry" b3 ff 0040h: 72 62 00 0043h: 72 46 00 <-- given the next instruction is already at 46h, this looks like a "nop"...0046h: 93 "monster" b2 "That's too bad" b3 ff005fh: 72 62 00 0062h: 91 <-- I wonder too0063h: 73 20 00 <-- this 0x0020 points "nicely" to the 11 10 ... at the 0084h line, so it could mean 73 is a "jump offset"0066h: ff ff ff ff 006ah: 2b 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 0084h: 11 10 20 01 10 20 60 01 30 90 73008fh: 11 18 20 01 18 20 60 01 30 90 02 60 20 60 08 87 40 70 29 00 01 18 20 60 01 40 70 29 00 12 70 20 02 80 20 90 60 20 60 23 92 73
I will continue to look at it tomorrow, right now it's already 5am and I should be in bed. Cya.
60: Argument of 1 byte, "Push1Con by:constant"
        () -- (xx)

72: Argument of 2 bytes, "Goto wr:addr"
        () -- ()
An unconditional goto to the selected address.

91 - Pop variable from stack

93: Variable arguments, "LoadString var:string"
       ??? -- ???
Loads a string into memory.  Possible displays it immediately too; unsure.  FF is the terminator, and EA-F1 means a 2-byte char follows.  Standard FF7 string rules.


Why you guys aren't use terrence description of opcodes? He describe all of them.
 
Mainly because no one told me it existed... and I spent arround 30 mins trying to find info before starting to get into it.

OMG for some reason I totally ignored the second post in this thread O_O. Anyway, the link is dead and I can't seem to find it arround. :/
 
No, not dead, just referer-protected. Visit gamefaqs.com first, then copy and paste that link into the address bar so it looks like you're coming from the gamefaqs.com domain.
 
Hm I coded a disassembler following the instructions in Terence's Enemy AI thread... it's not really useful right now, but I will later try to add some "parsing" to get it to a higher level.
 
So just refresh my memory, looks like you are trying to work on the AI script or on the whole scene file?
 
I'm working on the whole file, but for now specially on the "known" info... right now the program outputs most the data that was in the wiki in xml format (the scripts are just a block of text in a <SECTION> tag inside the <AI> tag).
My idea was to be able to export all the data as a big xml file, with "decompiled scripts"... I really like to get files with unknown data and find out what's inside, even tho my skills aren't too good. :P
 
Heh that's what I was planning on doing but I got so frustrated with the data not looking right (in fact the proper term is quite angry) I stoped. No point working on something that frustrates you too much. I threw out all the code for the last 3 weeks and really can't see why it didn't work.  Too frustrating to think about it. So I'll help Akari with the field models instead (he/she is making progress on it).  They did some screwy things with those to say the least (GRRR).

Err I forgot to actually say something.  I threw out most of my SCENE.BIN. gigaherz would you mind showing me the code you are using for SCENE.BIN?

I have to rewrite my whole decoder.  I was trying to use that to build a nice class to return data for combat.

Here is my battle structurve information retrieval strctures (the start of them).  I got so tangled up in the data not looking right (Sigh) I stopped working on this.  Mostly it returns information needed from the SCENE.BIN data files passed to it.  Then when it's destroyed that data can be deallocated or cleared and something else reloaded. That was the idea at least.  I didn't add the doxygen documentation comments either. (lazy me!)

Code: [Select]
Code:
//---------------------------------------------------------------------------#ifndef BattleInfoUintH#define BattleInfoUintH//---------------------------------------------------------------------------#include <string>#include "types.h"//---------------------------------------------------------------------------extern std::string FF7char2String(void *, int);//---------------------------------------------------------------------------class EnemyElement{   private:      char *Info;   public:      EnemyElement() {  Info = NULL; }      EnemyElement(void *);      int   Type(void) { return (int)GetUINT8(Info); }      int   Damage(void){return (int)GetUINT8(Info + 0x008); }};//---------------------------------------------------------------------------class EnemyItem{   private:      char *Info;   public:      EnemyItem();      EnemyItem(void *);      float Drop();      int   ID();};//---------------------------------------------------------------------------class EnemyStats{   private:      char *Info;   public:      EnemyStats();      EnemyStats(void *);      int   Level()  {  return (int)GetUINT8(Info + 0x020); }      int   Speed()  {  return (int)GetUINT8(Info + 0x021); }      int   Luck()   {  return (int)GetUINT8(Info + 0x022); }      int   Evade()  {  return (int)GetUINT8(Info + 0x023); }      int   Strength(){  return (int)GetUINT8(Info + 0x024); }      int   Defense(){  return (int)GetUINT8(Info + 0x025); }      int   Magic()  {  return (int)GetUINT8(Info + 0x026); }      int   MagicDefense(){  return (int)GetUINT8(Info + 0x020); }};//---------------------------------------------------------------------------class BattleEnemy{   private:      char *Info[3];   public:      BattleEnemy();      BattleEnemy(void *, int);      ~BattleEnemy();      std::string Name();      EnemyStats  Stats();      EnemyElement   Elements(int);      int         ID() { return (int)GetUINT16(Info[0]); }      int         Attacks(int Index) {         return (int)GetUINT16(Info[1] + 0x0048 + 2 *Index); }      EnemyItem   Item(int);      int         MP() { return (int)GetUINT16(Info[1] + 0x009C); }      int         AP() { return (int)GetUINT16(Info[1] + 0x009E); }      int         Morph() { return GetUINT16(Info[1] + 0x00A0); }      int         HP() { return GetINT32(Info[1] + 0x00A4); }      int         EXP() { return GetINT32(Info[1] + 0x00A8); }      int         Gil() { return GetINT32(Info[1] + 0x00AC); }};//---------------------------------------------------------------------------class BattleSet{   private:      char *Info[3];   public:      BattleSet();      BattleSet(void *, int);      int      Stage(void);};//---------------------------------------------------------------------------class BattleAttack{   private:      char       *Info[3];   public:      std::string Name();      int         ID();      BattleAttack();      BattleAttack(void *, int);};//---------------------------------------------------------------------------class BattleScene{   private:      char *RawData;      int   RawSize;      BattleSet   NullBS;      BattleEnemy NullBE;      BattleAttack NullBA;      BattleSet   *Battles[4];      BattleEnemy *Enemies[3];      BattleAttack*Attacks[32];      Init(void *);   public:      BattleSet   &Battle(int);      BattleEnemy &Enemy(int);      BattleAttack&Attack(int);      Assign(void *);      BattleScene();      BattleScene(void *);      ~BattleScene();};//---------------------------------------------------------------------------#endif
Cyb
 
Last edited:
Here is my code: http://www.sendspace.com/file/uxmsct
There is a .bat in /debug/, use it to run the app. I made a .dtd for it so I could validate the xml info.
If you prefer to help Akari instead, I could convert my code into your class myself...
 
Right so I changed the decoding routine to what yours used.
It looks like the LZS decompression code that has been used for eons here, is wrong.
Apart from that I now have more sensible data to look at so I can continue with my nice clean classes to export data.

My guess is it was the compression settings for decompression that was giving me failures. Not a big deal.

Erstwhile I'm going to also see if the BCX and BSX files clean up nicely using the same changes.

Cyb
 
LZS? scene.bin uses gzip :/ if you tried to decode a gzip stream using the LZS decoder, thne no wonder the results came out fucked... :P
 
Right so I fixed my decompression using the proper ZLIB calls (COUGH COUGH) and now I have this as the result.
I also improved the FF7 -> string conversion because sometimes it was using symbols that you would normally never see. Why? There are 9 or 10 special pyramid test objects.  In fact you can see the encoding in the image http://www.geocities.com/cyberman_phillips/Images/FF7_view.png.
I'll probably dump the SCENE data into the list space you see to the left. IE 1-250. Selecting that will dump into the right pane details of each horror.. I mean part of the battle scene :)

So my structures sort of work right now, they do not return the complete script like gigahertz does but that will be later.  Since each scripts are for the individual enemys listed in the file record, I'll probably create a battle script and add a battle script class to return the length and individual opcodes of a battle script, maybe even a dump function that returns a string to a complete "Disassembly" of the script itself.

Cyb
 
Last edited:
I've significantly modified the 'TDBView" now general Playstation ISO file viewer.  It was quite helpful in view a number of files and there data. Not perfect that is a certainty I've added viewing ISO image file sets.  I made this to test my Q-gears ISO code.  :D Seems to work!

http://www.sendspace.com/file/puy3ru TDBView.rar latest.

Cyb

PS
Side note it looks like the first 5 'files' aren't used in the game but are purely for debugging purposes. As you can see by the odd names they have and the weird attack names and numbers (save Bolt 3 and Cure 3).
 
Status
Not open for further replies.
Back
Top