Aller au contenu

Photo

Some GDA file format questions.


  • Veuillez vous connecter pour répondre
32 réponses à ce sujet

#1
0x30A88

0x30A88
  • Members
  • 1 081 messages
I am trying to write a C# class for GDA files and have a decent understandning of the file format. A such class would open for some nice opportunities in my opinion. Like a more friendly way to create AL templates or manage rewards to name a few. I have some questions though.

1. In the raw data block, there are column headers that have a 4 byte hash, 1 byte type id and 3 bytes of padding. Are there any way I can find what the hash stand for? I tried looking up the number in the talk table to no avail. Is there another DLL I have to peek through, if so, which one?
2. What are all types that the 2DA tables use and what are their IDs? I know (0, 1, 2 = int, string, float), but are there more of them? And what is the ID for talk-table references?

Thanks in advance
- Gisle Aune

#2
CID-78

CID-78
  • Members
  • 1 124 messages
A .GDA is a GFF file so read the GFF file format in the datoolsetwiki. the hash is just the key for a column name. Instead of processing a string they hash it, if the hash match the column it's a hit.

much faster lookup speed. and there is a very slim chance that two strings produce the same hash in the same table.

#3
CID-78

CID-78
  • Members
  • 1 124 messages
there is already a GDA app here:
http://social.bioware.com/project/755/

Check it out before you spend time building something that do the same thing.

#4
0x30A88

0x30A88
  • Members
  • 1 081 messages
I know of GDApp. I try only to make a C# class to handle GDA files. How can I get the column name then? I see GDApp has done that and I wonder how that is stored. It's mostly a challange for myself to create a GDA class and if it all happen to work, it could prove useful for smaller tools like an easier way to create ALTables or manage quest rewards. My original questions still stand however.

I know it's a GFF file too, but I have ideas for how to get it written down. It's the hash comes before the row type and the padding.

I will post it when I get it to work for others to see and chew me out for whatever little flaw there is in there, when I get it tested.

Modifié par Gisle Aune, 05 août 2011 - 10:38 .


#5
ChewyGumball

ChewyGumball
  • Members
  • 282 messages
You can rename it as a .gff file and then open it in the editor for a visual representation of the file. I found that most useful.

#6
0x30A88

0x30A88
  • Members
  • 1 081 messages
Yeah, I have done that and all. I did not claim to have a problem outside the two questions in the OP. Other than that, I kind of understand the GFF file format's usage for GDAs. How do I get the column names based on these? Let's take a slice of the hex dump

14 00 00 00 08 00 00 00 3c 00 00 00 06 00 00 00
36 c9 fb 66 01 ff ff ff 5d df c5 fe 01 ff ff ff
6e eb 11 d6 01 ff ff ff 1a 64 4a 8c 01 ff ff ff
ba b4 44 d6 01 ff ff ff 1f 32 9e 9f 02 ff ff ff
55 00 00 00 00 00 00 00 55 00 00 00 15 00 00 1d

See the underlined part and the 5 similiar numbers. Opening it up in the GFF editor to see a number in the millions say just as little.

(bolded part = raw data block's first integer)

Modifié par Gisle Aune, 05 août 2011 - 11:50 .


#7
ChewyGumball

ChewyGumball
  • Members
  • 282 messages
Post the struct definition as well. the raw data means nothing without it.

#8
0x30A88

0x30A88
  • Members
  • 1 081 messages
It's a simple G2DA with 6 columns as these look quite similiar, with the difference being the amount of bytes in the row list entries and row list count. Some parts of this file format seems quite unoptimized in my opinion, like padding and 16 bits of bit flags for three flags.

47 46 46 20 56 34 2e 30 50 43 20 20 47 32 44 41
56 30 2e 32 03 00 00 00 c4 00 00 00 67 74 6f 70 (gtop)
02 00 00 00 4c 00 00 00 08 00 00 00 63 6f 6c 6d (colm)
02 00 00 00 64 00 00 00 08 00 00 00 72 6f 77 73 (rows)
06 00 00 00 7c 00 00 00 18 00 00 00 12 27 00 00
01 00 00 c0 00 00 00 00 13 27 00 00 02 00 00 c0
04 00 00 00 11 27 00 00 04 00 00 00 00 00 00 00
f7 2a 00 00 00 00 00 00 04 00 00 00 15 27 00 00
05 00 00 00 00 00 00 00 16 27 00 00 05 00 00 00
04 00 00 00 17 27 00 00 05 00 00 00 08 00 00 00
18 27 00 00 05 00 00 00 0c 00 00 00 19 27 00 00
05 00 00 00 10 00 00 00 1a 27 00 00 08 00 00 00
14 00 00 00 08 00 00 00 3c 00 00 00 06 00 00 00
That makes it a valid 2DA with 6 row lists, for my class all this is only relevant upon saving it. I don't see how this will make my questions in the OP any clearer though. What is the underlined numbers in my last post storing?

Modifié par Gisle Aune, 06 août 2011 - 12:43 .


#9
CID-78

CID-78
  • Members
  • 1 124 messages
you don't get a string from a hash ever. it's a one way process. the name is in the .xls sheet for the .2da and is also used in the function calls. which is hashed by the same method.

you can of course recognise a string by a hash. if you knew about it from the beginning. ie the same string will allways produce the same hash. so if you got both you can recognise them. if your missing the string, you will never now. because there is multiple strings in theory that produce the same hash. in reality those other string are unreadable junk.

#10
0x30A88

0x30A88
  • Members
  • 1 081 messages
Are there any lists I can compare them witn? Or is the spesific hashing method possible for me to replicate?

Also, my other question still stands.

#11
CID-78

CID-78
  • Members
  • 1 124 messages
if you decompile the excelprocessor you should be able to find the hash method. It's probably something simple like a checksum of some kind.

the second question is in the GFF format description:
http://social.biowar...t/index.php/GFF

#12
CID-78

CID-78
  • Members
  • 1 124 messages
the hash algorithm is noted at the bottom of this page:
http://social.biowar...t/index.php/GDA

#13
0x30A88

0x30A88
  • Members
  • 1 081 messages
Thank you. The type list there is not the same as the one the GDA columns seem to use, where 0 = int, 1 = string pointer in file, 2 = float, ...

#14
CID-78

CID-78
  • Members
  • 1 124 messages
shouldn't be hard for you to figure them out. .2das doesn't have more then a few types. And please update the wiki with the format information when you do.

#15
FollowTheGourd

FollowTheGourd
  • Members
  • 572 messages
They were right the last time I checked. I made a post detailing some of what I'd figured out here about a year ago: http://social.biowar...72/index/508109
If the field types don't look right to you, make sure they aren't being OR'd with some other flags.


It's been a while, but I'm not sure why you're talking about the type information in the raw data block.

If you want the actual names of every column like "Label", "Name", etc, I think you just have to go through the 2DA sources and CRC32 them to create a reverse lookup table.

Also, BioSpirit figured out where the constant names are stored in EditorGff40.dll, if that's what you were also asking about. But IIRC all that matters is already known - "gtop", "colm", and "rows".

Modifié par FollowTheGourd, 06 août 2011 - 07:46 .


#16
0x30A88

0x30A88
  • Members
  • 1 081 messages
That's the source I got most information about the file format from. What I meant by type info is the padded UINT8 there (01 ff ff ff for instance). I just wondered how many of these did exist, I know of string pointer (to a position in the file) being 0, int being 1 and float being 2. I have yet to see if talk table references have their own type ID as I think they are unsigned, for it makes no sense otherwise.

#17
FollowTheGourd

FollowTheGourd
  • Members
  • 572 messages
I see. I haven't checked it, but I suspect then that GDAs only support TLK strings with IDs no higher than 2^31-1, as all I recall ever seeing in 2DAs are ints for what gets looked up in game from the talk table. According to the wiki on GFF, there's a TLKString type (pair of UInt32s), but I think we'd be limited by what ExcelProcessor handles, unless crafting your own GDA can get around that.

Modifié par FollowTheGourd, 06 août 2011 - 08:47 .


#18
0x30A88

0x30A88
  • Members
  • 1 081 messages
It seems the spreadsheets use int for them too. So out of all the 2DA tables I have seen in Excel and their compiled GDA counterpart, there seems to be only strings (0), int (1) and float (2). (G2DA_COLUMN_TYPE values in parantheses)

Modifié par Gisle Aune, 06 août 2011 - 09:48 .


#19
CID-78

CID-78
  • Members
  • 1 124 messages
if you look on the script functions you can only read int,floats and strings from .2da's or m2das.So there shouldn't be more types then that.

#20
0x30A88

0x30A88
  • Members
  • 1 081 messages
Good news, the code loads the GDA files perfectly now for ints, strings and floats. Elys just gave me the code, though I couldn't understand Delphi, I saw that there are two additional types. Boolean (4) and Resource (5). GetValue<T> also works, though it gives an exception on wrong type, which should be no hard feat to test for and avoid, the 'is' operator works for that and I could treat it as I do when an invalidly high column or row index is passed to the method, which is returning default of type, usually null.

Is 2DA_BASE.xls exporting wrongly? Both Elys' GDApp and my read function differs from it.
Excel: 0, animations, ANIM_, **** (=0)
GDApp and my code: 0, Gender Information, gender, 0

I will post the class' code when I get adding rows, deleting rows and such working, which I have written, but not tested. As well as saving it, though I think I know how to approach that.

Modifié par Gisle Aune, 07 août 2011 - 11:25 .


#21
elys

elys
  • Members
  • 458 messages
Exporting 2DA_BASE.XLS with ExcelProcessor, will generate 2 files: 2DA_BASE.GDA, and M2DA_BASE.GDA.

Use M2DA_BASE.GDA to compare it with 2DA_BASE.XLS for your tests.

Modifié par elys, 07 août 2011 - 11:07 .


#22
0x30A88

0x30A88
  • Members
  • 1 081 messages
Made a project now. Full method list and I will post the stuff there when finished.
http://social.biowar...m/project/4953/

I am working on the save function. If anyone has information that might help on understanding the 01.00.00.c0 part, I would be grateful.
EDIT: After a bit of research, I got it now. I can now work on the raw data. Anyone have any info on how boolean and resources are stored? I really hope for 4-byte int and string though, shouldn't be hard to find out.

Modifié par Gisle Aune, 08 août 2011 - 01:12 .


#23
elys

elys
  • Members
  • 458 messages
Boolean only need to be stored as one byte, but you can save them as 4 bytes if u want or even 100 bytes if you wished. The data length does not matter as long as the data descriptor matches the length you decide to use. That's how GFF file support data padding.

Resources are stored the same way as strings.

Modifié par elys, 08 août 2011 - 02:27 .


#24
0x30A88

0x30A88
  • Members
  • 1 081 messages
That's nice. The saving function now works all the way to the raw data block and the pointer is correct. C# had no built in CRC32, but it was not hard to find one as easy as converting the label string to a byte array. Where is the boolean's size stored? (for loading's sake).

It might be possible that I can post it today, as everything is going smoothly.

#25
elys

elys
  • Members
  • 458 messages
For any type of data, the size if stored in the struct descriptor, in StructSize (if you use the same names than the GFF details on Wiki )

Wait, I had a doubt since I had not looked at this stuff for a long while. So I went back to it quickly. 
So here it goes:

In your case for the Boolean, what matters is that  Field Type = GFF_INT8 (1), and that the Field Index (4-byte unsigned offset to the location of the data from the beginning of the struct in the data block) is correctly pointing to your 4-byte stored boolean. 

Anyway only the first byte will be read by the game since the engine is waiting for a GFF_INT8 according to the Field Type.

Modifié par elys, 08 août 2011 - 02:31 .